1 18 package org.apache.batik.bridge; 19 20 import java.awt.Cursor ; 21 import java.awt.RenderingHints ; 22 import java.awt.geom.AffineTransform ; 23 import java.awt.geom.Rectangle2D ; 24 25 import org.apache.batik.css.engine.CSSEngine; 26 import org.apache.batik.dom.svg.SVGOMCSSImportedElementRoot; 27 import org.apache.batik.dom.svg.SVGOMDocument; 28 import org.apache.batik.dom.svg.SVGOMUseElement; 29 import org.apache.batik.dom.util.XLinkSupport; 30 import org.apache.batik.gvt.CompositeGraphicsNode; 31 import org.apache.batik.gvt.GraphicsNode; 32 import org.w3c.dom.Attr ; 33 import org.w3c.dom.Element ; 34 import org.w3c.dom.NamedNodeMap ; 35 import org.w3c.dom.Node ; 36 import org.w3c.dom.events.Event ; 37 import org.w3c.dom.events.EventListener ; 38 import org.w3c.dom.events.EventTarget ; 39 import org.w3c.dom.events.MutationEvent ; 40 41 47 public class SVGUseElementBridge extends AbstractGraphicsNodeBridge { 48 53 protected ReferencedElementMutationListener l; 54 55 protected BridgeContext subCtx=null; 56 57 60 public SVGUseElementBridge() {} 61 62 65 public String getLocalName() { 66 return SVG_USE_TAG; 67 } 68 69 72 public Bridge getInstance(){ 73 return new SVGUseElementBridge(); 74 } 75 76 83 public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) { 84 if (!SVGUtilities.matchUserAgent(e, ctx.getUserAgent())) 86 return null; 87 88 CompositeGraphicsNode gn = buildCompositeGraphicsNode(ctx, e, null); 89 90 return gn; 91 } 92 93 103 public CompositeGraphicsNode buildCompositeGraphicsNode 104 (BridgeContext ctx, Element e, 105 CompositeGraphicsNode gn) { 106 String uri = XLinkSupport.getXLinkHref(e); 108 if (uri.length() == 0) { 109 throw new BridgeException(e, ERR_ATTRIBUTE_MISSING, 110 new Object [] {"xlink:href"}); 111 } 112 113 Element refElement = ctx.getReferencedElement(e, uri); 114 115 SVGOMDocument document 116 = (SVGOMDocument)e.getOwnerDocument(); 117 SVGOMDocument refDocument 118 = (SVGOMDocument)refElement.getOwnerDocument(); 119 boolean isLocal = (refDocument == document); 120 121 BridgeContext theCtx = ctx; 122 subCtx = null; 123 if (!isLocal) { 124 CSSEngine eng = refDocument.getCSSEngine(); 125 subCtx = (BridgeContext)refDocument.getCSSEngine().getCSSContext(); 126 theCtx = subCtx; 127 } 128 129 Element localRefElement = 131 (Element)document.importNode(refElement, true, true); 132 133 if (SVG_SYMBOL_TAG.equals(localRefElement.getLocalName())) { 134 Element svgElement 138 = document.createElementNS(SVG_NAMESPACE_URI, SVG_SVG_TAG); 139 NamedNodeMap attrs = localRefElement.getAttributes(); 141 int len = attrs.getLength(); 142 for (int i = 0; i < len; i++) { 143 Attr attr = (Attr )attrs.item(i); 144 svgElement.setAttributeNS(attr.getNamespaceURI(), 145 attr.getName(), 146 attr.getValue()); 147 } 148 for (Node n = localRefElement.getFirstChild(); 150 n != null; 151 n = localRefElement.getFirstChild()) { 152 svgElement.appendChild(n); 153 } 154 localRefElement = svgElement; 155 } 156 157 if (SVG_SVG_TAG.equals(localRefElement.getLocalName())) { 158 String wStr = e.getAttributeNS(null, SVG_WIDTH_ATTRIBUTE); 163 if (wStr.length() != 0) { 164 localRefElement.setAttributeNS 165 (null, SVG_WIDTH_ATTRIBUTE, wStr); 166 } 167 String hStr = e.getAttributeNS(null, SVG_HEIGHT_ATTRIBUTE); 168 if (hStr.length() != 0) { 169 localRefElement.setAttributeNS 170 (null, SVG_HEIGHT_ATTRIBUTE, hStr); 171 } 172 } 173 174 SVGOMCSSImportedElementRoot root; 176 root = new SVGOMCSSImportedElementRoot(document, e, isLocal); 177 root.appendChild(localRefElement); 178 179 if (gn == null) { 180 gn = new CompositeGraphicsNode(); 181 } else { 182 int s = gn.size(); 183 for (int i=0; i<s; i++) 184 gn.remove(0); 185 } 186 187 SVGOMUseElement ue = (SVGOMUseElement)e; 188 Node oldRoot = ue.getCSSImportedElementRoot(); 189 if (oldRoot != null) { 190 disposeTree(oldRoot); 191 } 192 ue.setCSSImportedElementRoot(root); 193 194 Element g = localRefElement; 195 196 CSSUtilities.computeStyleAndURIs(refElement, localRefElement, uri); 198 199 GVTBuilder builder = ctx.getGVTBuilder(); 200 GraphicsNode refNode = builder.build(ctx, g); 201 202 204 gn.getChildren().add(refNode); 205 206 gn.setTransform(computeTransform(e, ctx)); 207 208 211 gn.setVisible(CSSUtilities.convertVisibility(e)); 213 214 RenderingHints hints = null; 215 hints = CSSUtilities.convertColorRendering(e, hints); 216 if (hints != null) 217 gn.setRenderingHints(hints); 218 219 Rectangle2D r = CSSUtilities.convertEnableBackground(e); 221 if (r != null) 222 gn.setBackgroundEnable(r); 223 224 if (l != null) { 225 EventTarget target = l.target; 227 target.removeEventListener("DOMAttrModified", l, true); 228 target.removeEventListener("DOMNodeInserted", l, true); 229 target.removeEventListener("DOMNodeRemoved", l, true); 230 target.removeEventListener("DOMCharacterDataModified",l, true); 231 l = null; 232 } 233 234 236 if (isLocal && ctx.isDynamic()) { 239 l = new ReferencedElementMutationListener(); 240 241 EventTarget target = (EventTarget )refElement; 242 l.target = target; 243 244 target.addEventListener("DOMAttrModified", l, true); 245 theCtx.storeEventListener(target, "DOMAttrModified", l, true); 246 247 target.addEventListener("DOMNodeInserted", l, true); 248 theCtx.storeEventListener(target, "DOMNodeInserted", l, true); 249 250 target.addEventListener("DOMNodeRemoved", l, true); 251 theCtx.storeEventListener(target, "DOMNodeRemoved", l, true); 252 253 target.addEventListener("DOMCharacterDataModified", l, true); 254 theCtx.storeEventListener 255 (target, "DOMCharacterDataModified", l, true); 256 } 257 258 return gn; 259 } 260 261 public void dispose() { 262 if (l != null) { 263 EventTarget target = l.target; 265 target.removeEventListener("DOMAttrModified", l, true); 266 target.removeEventListener("DOMNodeInserted", l, true); 267 target.removeEventListener("DOMNodeRemoved", l, true); 268 target.removeEventListener("DOMCharacterDataModified",l, true); 269 l = null; 270 } 271 272 SVGOMUseElement ue = (SVGOMUseElement)e; 273 if ((ue != null) && (ue.getCSSImportedElementRoot() != null)) { 274 disposeTree(ue.getCSSImportedElementRoot()); 275 } 276 277 super.dispose(); 278 279 subCtx = null; 280 } 281 282 285 protected AffineTransform computeTransform(Element e, BridgeContext ctx) { 286 UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, e); 287 288 float x = 0; 290 String s = e.getAttributeNS(null, SVG_X_ATTRIBUTE); 291 if (s.length() != 0) { 292 x = UnitProcessor.svgHorizontalCoordinateToUserSpace 293 (s, SVG_X_ATTRIBUTE, uctx); 294 } 295 296 float y = 0; 298 s = e.getAttributeNS(null, SVG_Y_ATTRIBUTE); 299 if (s.length() != 0) { 300 y = UnitProcessor.svgVerticalCoordinateToUserSpace 301 (s, SVG_Y_ATTRIBUTE, uctx); 302 } 303 304 s = e.getAttributeNS(null, SVG_TRANSFORM_ATTRIBUTE); 307 AffineTransform at = AffineTransform.getTranslateInstance(x, y); 308 309 if (s.length() != 0) { 311 at.preConcatenate 312 (SVGUtilities.convertTransform(e, SVG_TRANSFORM_ATTRIBUTE, s)); 313 } 314 315 return at; 316 } 317 318 322 protected GraphicsNode instantiateGraphicsNode() { 323 return null; } 325 326 329 public boolean isComposite() { 330 return false; 331 } 332 333 341 public void buildGraphicsNode(BridgeContext ctx, 342 Element e, 343 GraphicsNode node) { 344 345 super.buildGraphicsNode(ctx, e, node); 346 347 if (ctx.isInteractive()) { 348 EventTarget target = (EventTarget )e; 349 EventListener l = new CursorMouseOverListener(ctx); 350 target.addEventListener(SVG_EVENT_MOUSEOVER, l, false); 351 ctx.storeEventListener(target, SVG_EVENT_MOUSEOVER, l, false); 352 } 353 } 354 355 358 public static class CursorMouseOverListener implements EventListener { 359 360 protected BridgeContext ctx; 361 public CursorMouseOverListener(BridgeContext ctx) { 362 this.ctx = ctx; 363 } 364 365 public void handleEvent(Event evt) { 366 Element currentTarget = (Element)evt.getCurrentTarget(); 371 372 if (!CSSUtilities.isAutoCursor(currentTarget)) { 373 Cursor cursor; 374 cursor = CSSUtilities.convertCursor(currentTarget, ctx); 375 if (cursor != null) { 376 ctx.getUserAgent().setSVGCursor(cursor); 377 } 378 } 379 } 380 } 381 382 385 public class ReferencedElementMutationListener implements EventListener { 386 EventTarget target; 387 388 public void handleEvent(Event evt) { 389 buildCompositeGraphicsNode(ctx, e, (CompositeGraphicsNode)node); 395 } 396 } 397 398 400 403 public void handleDOMAttrModifiedEvent(MutationEvent evt) { 404 String attrName = evt.getAttrName(); 405 Node evtNode = evt.getRelatedNode(); 406 407 if ((evtNode.getNamespaceURI() == null) && 408 (attrName.equals(SVG_X_ATTRIBUTE) || 409 attrName.equals(SVG_Y_ATTRIBUTE) || 410 attrName.equals(SVG_TRANSFORM_ATTRIBUTE))) { 411 node.setTransform(computeTransform(e, ctx)); 412 handleGeometryChanged(); 413 } else if (((evtNode.getNamespaceURI() == null) && 414 (attrName.equals(SVG_WIDTH_ATTRIBUTE) || 415 attrName.equals(SVG_HEIGHT_ATTRIBUTE))) || 416 (( XLinkSupport.XLINK_NAMESPACE_URI.equals 417 (evtNode.getNamespaceURI()) ) && 418 SVG_HREF_ATTRIBUTE.equals(evtNode.getLocalName()))) { 419 buildCompositeGraphicsNode(ctx, e, (CompositeGraphicsNode)node); 420 } 421 } 422 } 423 | Popular Tags |