| 1 18 package org.apache.batik.bridge; 19 20 import java.awt.Cursor ; 21 import java.awt.geom.Dimension2D ; 22 import java.io.IOException ; 23 import java.io.InterruptedIOException ; 24 import java.lang.ref.SoftReference ; 25 import java.net.MalformedURLException ; 26 import java.net.URL ; 27 import java.util.HashMap ; 28 import java.util.HashSet ; 29 import java.util.Iterator ; 30 import java.util.LinkedList ; 31 import java.util.List ; 32 import java.util.ListIterator ; 33 import java.util.Map ; 34 import java.util.Set ; 35 import java.util.WeakHashMap ; 36 37 import org.apache.batik.bridge.svg12.SVG12BridgeExtension; 38 import org.apache.batik.css.engine.CSSContext; 39 import org.apache.batik.css.engine.CSSEngine; 40 import org.apache.batik.css.engine.CSSEngineEvent; 41 import org.apache.batik.css.engine.CSSEngineListener; 42 import org.apache.batik.css.engine.CSSEngineUserAgent; 43 import org.apache.batik.css.engine.SVGCSSEngine; 44 import org.apache.batik.css.engine.SystemColorSupport; 45 import org.apache.batik.css.engine.value.Value; 46 import org.apache.batik.dom.svg.SVGContext; 47 import org.apache.batik.dom.svg.SVGDOMImplementation; 48 import org.apache.batik.dom.svg.SVGOMDocument; 49 import org.apache.batik.dom.svg.SVGOMElement; 50 import org.apache.batik.dom.svg.SVGStylableElement; 51 import org.apache.batik.gvt.CompositeGraphicsNode; 52 import org.apache.batik.gvt.GraphicsNode; 53 import org.apache.batik.gvt.TextPainter; 54 import org.apache.batik.script.Interpreter; 55 import org.apache.batik.script.InterpreterPool; 56 import org.apache.batik.util.CSSConstants; 57 import org.apache.batik.util.CleanerThread; 58 import org.apache.batik.util.ParsedURL; 59 import org.apache.batik.util.SVGConstants; 60 import org.apache.batik.util.Service; 61 62 import org.w3c.dom.Document ; 63 import org.w3c.dom.Element ; 64 import org.w3c.dom.Node ; 65 import org.w3c.dom.events.Event ; 66 import org.w3c.dom.events.EventListener ; 67 import org.w3c.dom.events.EventTarget ; 68 import org.w3c.dom.events.MouseEvent ; 69 import org.w3c.dom.events.MutationEvent ; 70 import org.w3c.dom.svg.SVGDocument; 71 72 85 public class BridgeContext implements ErrorConstants, CSSContext { 86 87 90 protected Document document; 91 92 95 protected GVTBuilder gvtBuilder; 96 97 102 protected Map interpreterMap = new HashMap (7); 103 104 109 private Map fontFamilyMap; 110 111 116 protected Map viewportMap = new WeakHashMap (); 117 118 121 protected List viewportStack = new LinkedList (); 122 123 126 protected UserAgent userAgent; 127 128 133 protected Map elementNodeMap; 134 135 140 protected Map nodeElementMap; 141 142 147 protected Map namespaceURIMap; 148 149 159 protected Map elementDataMap; 160 161 162 165 protected InterpreterPool interpreterPool; 166 167 170 protected DocumentLoader documentLoader; 171 172 175 protected Dimension2D documentSize; 176 177 181 protected TextPainter textPainter; 182 183 189 public final static int STATIC = 0; 190 195 public final static int INTERACTIVE = 1; 196 197 202 public final static int DYNAMIC = 2; 203 204 207 protected int dynamicStatus = STATIC; 208 209 212 protected UpdateManager updateManager; 213 214 217 protected BridgeContext() {} 218 219 222 private static InterpreterPool sharedPool = new InterpreterPool(); 223 224 228 public BridgeContext(UserAgent userAgent) { 229 this(userAgent, 230 sharedPool, 231 new DocumentLoader(userAgent)); 232 } 233 234 239 public BridgeContext(UserAgent userAgent, 240 DocumentLoader loader) { 241 this(userAgent, sharedPool, loader); 242 } 243 244 250 public BridgeContext(UserAgent userAgent, 251 InterpreterPool interpreterPool, 252 DocumentLoader documentLoader) { 253 this.userAgent = userAgent; 254 this.viewportMap.put(userAgent, new UserAgentViewport(userAgent)); 255 this.interpreterPool = interpreterPool; 256 this.documentLoader = documentLoader; 257 } 258 259 262 protected void initializeDocument(Document document) { 263 SVGOMDocument doc = (SVGOMDocument)document; 264 CSSEngine eng = doc.getCSSEngine(); 265 if (eng == null) { 266 SVGDOMImplementation impl; 267 impl = (SVGDOMImplementation)doc.getImplementation(); 268 eng = impl.createCSSEngine(doc, this); 269 eng.setCSSEngineUserAgent(new CSSEngineUserAgentWrapper(userAgent)); 270 doc.setCSSEngine(eng); 271 eng.setMedia(userAgent.getMedia()); 272 String uri = userAgent.getUserStyleSheetURI(); 273 if (uri != null) { 274 try { 275 URL url = new URL (uri); 276 eng.setUserAgentStyleSheet 277 (eng.parseStyleSheet(url, "all")); 278 } catch (MalformedURLException e) { 279 userAgent.displayError(e); 280 } 281 } 282 eng.setAlternateStyleSheet(userAgent.getAlternateStyleSheet()); 283 } 284 } 285 286 289 public CSSEngine getCSSEngineForElement(Element e) { 290 SVGOMDocument doc = (SVGOMDocument)e.getOwnerDocument(); 291 return doc.getCSSEngine(); 292 } 293 294 296 303 public void setTextPainter(TextPainter textPainter) { 304 this.textPainter = textPainter; 305 } 306 307 310 public TextPainter getTextPainter() { 311 return textPainter; 312 } 313 314 317 public Document getDocument() { 318 return document; 319 } 320 321 326 protected void setDocument(Document document) { 327 if (this.document != document){ 328 fontFamilyMap = null; 329 } 330 this.document = document; 331 registerSVGBridges(); 332 } 333 334 337 public Map getFontFamilyMap(){ 338 if (fontFamilyMap == null){ 339 fontFamilyMap = new HashMap (); 340 } 341 return fontFamilyMap; 342 } 343 344 349 protected void setFontFamilyMap(Map fontFamilyMap) { 350 this.fontFamilyMap = fontFamilyMap; 351 } 352 353 358 public void setElementData(Node n, Object data) { 359 if (elementDataMap == null) 360 elementDataMap = new WeakHashMap (); 361 elementDataMap.put(n, new SoftReference (data)); 362 } 363 364 369 public Object getElementData(Node n) { 370 if (elementDataMap == null) 371 return null; 372 Object o = elementDataMap.get(n); 373 if (o == null) return null; 374 SoftReference sr = (SoftReference )o; 375 o = sr.get(); 376 if (o == null) { 377 elementDataMap.remove(n); 378 } 379 return o; 380 } 381 382 385 public UserAgent getUserAgent() { 386 return userAgent; 387 } 388 389 393 protected void setUserAgent(UserAgent userAgent) { 394 this.userAgent = userAgent; 395 } 396 397 400 public GVTBuilder getGVTBuilder() { 401 return gvtBuilder; 402 } 403 404 407 protected void setGVTBuilder(GVTBuilder gvtBuilder) { 408 this.gvtBuilder = gvtBuilder; 409 } 410 411 414 public InterpreterPool getInterpreterPool() { 415 return interpreterPool; 416 } 417 418 421 public FocusManager getFocusManager() { 422 return focusManager; 423 } 424 425 428 public CursorManager getCursorManager() { 429 return cursorManager; 430 } 431 432 437 protected void setInterpreterPool(InterpreterPool interpreterPool) { 438 this.interpreterPool = interpreterPool; 439 } 440 441 446 public Interpreter getInterpreter(String language) { 447 if (document == null) { 448 throw new RuntimeException ("Unknown document"); 449 } 450 Interpreter interpreter = (Interpreter)interpreterMap.get(language); 451 if (interpreter == null) { 452 try { 453 interpreter = interpreterPool.createInterpreter(document, language); 454 interpreterMap.put(language, interpreter); 455 } catch (Exception e) { 456 if (userAgent != null) { 457 userAgent.displayError(e); 458 return null; 459 } 460 } 461 } 462 463 if (interpreter == null) { 464 if (userAgent != null) { 465 userAgent.displayError(new Exception ("Unknown language: " + language)); 466 } 467 } 468 469 return interpreter; 470 } 471 472 475 public DocumentLoader getDocumentLoader() { 476 return documentLoader; 477 } 478 479 483 protected void setDocumentLoader(DocumentLoader newDocumentLoader) { 484 this.documentLoader = newDocumentLoader; 485 } 486 487 491 public Dimension2D getDocumentSize() { 492 return documentSize; 493 } 494 495 500 protected void setDocumentSize(Dimension2D d) { 501 this.documentSize = d; 502 } 503 504 507 public boolean isDynamic() { 508 return (dynamicStatus == DYNAMIC); 509 } 510 511 514 public boolean isInteractive() { 515 return (dynamicStatus != STATIC); 516 } 517 518 526 public void setDynamicState(int status) { 527 dynamicStatus = status; 528 } 529 530 534 public void setDynamic(boolean dynamic) { 535 if (dynamic) 536 setDynamicState(DYNAMIC); 537 else 538 setDynamicState(STATIC); 539 } 540 541 545 public void setInteractive(boolean interactive) { 546 if (interactive) 547 setDynamicState(INTERACTIVE); 548 else 549 setDynamicState(STATIC); 550 } 551 552 553 556 public UpdateManager getUpdateManager() { 557 return updateManager; 558 } 559 560 563 protected void setUpdateManager(UpdateManager um) { 564 updateManager = um; 565 } 566 567 569 576 public Element getReferencedElement(Element e, String uri) { 577 try { 578 SVGDocument document = (SVGDocument)e.getOwnerDocument(); 579 URIResolver ur = new URIResolver(document, documentLoader); 580 Element ref = ur.getElement(uri, e); 581 if (ref == null) { 582 throw new BridgeException(e, ERR_URI_BAD_TARGET, 583 new Object [] {uri}); 584 } else { 585 SVGOMDocument refDoc = (SVGOMDocument)ref.getOwnerDocument(); 586 if (refDoc != document) { 594 CSSEngine eng = refDoc.getCSSEngine(); 595 if (eng == null) { 596 BridgeContext subCtx; 597 subCtx = new BridgeContext(getUserAgent(), 598 getDocumentLoader()); 599 subCtx.setGVTBuilder(getGVTBuilder()); 600 subCtx.setDocument(refDoc); 601 subCtx.initializeDocument(refDoc); 602 } 603 } 604 return ref; 605 } 606 } catch (MalformedURLException ex) { 607 throw new BridgeException(e, ERR_URI_MALFORMED, 608 new Object [] {uri}); 609 } catch (InterruptedIOException ex) { 610 throw new InterruptedBridgeException(); 611 } catch (IOException ex) { 612 throw new BridgeException(e, ERR_URI_IO, 613 new Object [] {uri}); 614 } catch (IllegalArgumentException ex) { 615 throw new BridgeException(e, ERR_URI_REFERENCE_A_DOCUMENT, 616 new Object [] {uri}); 617 } catch (SecurityException ex) { 618 throw new BridgeException(e, ERR_URI_UNSECURE, 619 new Object [] {uri}); 620 } 621 } 622 623 625 630 public Viewport getViewport(Element e) { 631 if (viewportStack != null) { 632 if (viewportStack.size() == 0) { 634 return (Viewport)viewportMap.get(userAgent); 636 } else { 637 return (Viewport)viewportStack.get(0); 639 } 640 } else { 641 e = SVGUtilities.getParentElement(e); 643 while (e != null) { 644 Viewport viewport = (Viewport)viewportMap.get(e); 645 if (viewport != null) { 646 return viewport; 647 } 648 e = SVGUtilities.getParentElement(e); 649 } 650 return (Viewport)viewportMap.get(userAgent); 651 } 652 } 653 654 660 public void openViewport(Element e, Viewport viewport) { 661 viewportMap.put(e, viewport); 662 if (viewportStack == null) { 663 viewportStack = new LinkedList (); 664 } 665 viewportStack.add(0, viewport); 666 } 667 668 public void removeViewport(Element e) { 669 viewportMap.remove(e); 670 } 671 672 676 public void closeViewport(Element e) { 677 viewportStack.remove(0); 679 if (viewportStack.size() == 0) { 680 viewportStack = null; 681 } 682 } 683 684 686 694 public void bind(Element element, GraphicsNode node) { 695 if (elementNodeMap == null) { 696 elementNodeMap = new WeakHashMap (); 697 nodeElementMap = new WeakHashMap (); 698 } 699 elementNodeMap.put(element, new SoftReference (node)); 700 nodeElementMap.put(node, new SoftReference (element)); 701 } 702 703 708 public void unbind(Element element) { 709 if (elementNodeMap == null) { 710 return; 711 } 712 GraphicsNode node = null; 713 SoftReference sr = (SoftReference )elementNodeMap.get(element); 714 if (sr != null) 715 node = (GraphicsNode)sr.get(); 716 elementNodeMap.remove(element); 717 if (node != null) 718 nodeElementMap.remove(node); 719 } 720 721 727 public GraphicsNode getGraphicsNode(Element element) { 728 if (elementNodeMap != null) { 729 SoftReference sr = (SoftReference )elementNodeMap.get(element); 730 if (sr != null) 731 return (GraphicsNode)sr.get(); 732 } 733 return null; 734 } 735 736 742 public Element getElement(GraphicsNode node) { 743 if (nodeElementMap != null) { 744 SoftReference sr = (SoftReference )nodeElementMap.get(node); 745 if (sr != null) 746 return (Element)sr.get(); 747 } 748 return null; 749 } 750 751 753 759 public boolean hasGraphicsNodeBridge(Element element) { 760 if (namespaceURIMap == null || element == null) { 761 return false; 762 } 763 String localName = element.getLocalName(); 764 String namespaceURI = element.getNamespaceURI(); 765 namespaceURI = ((namespaceURI == null)? "" : namespaceURI); 766 HashMap localNameMap = (HashMap ) namespaceURIMap.get(namespaceURI); 767 if (localNameMap == null) { 768 return false; 769 } 770 return (localNameMap.get(localName) instanceof GraphicsNodeBridge); 771 } 772 773 778 public Bridge getBridge(Element element) { 779 if (namespaceURIMap == null || element == null) { 780 return null; 781 } 782 String localName = element.getLocalName(); 783 String namespaceURI = element.getNamespaceURI(); 784 namespaceURI = ((namespaceURI == null)? "" : namespaceURI); 785 return getBridge(namespaceURI, localName); 786 } 787 788 795 public Bridge getBridge(String namespaceURI, String localName) { 796 HashMap localNameMap = (HashMap ) namespaceURIMap.get(namespaceURI); 797 if (localNameMap == null) { 798 return null; 799 } 800 Bridge bridge = (Bridge)localNameMap.get(localName); 801 if (isDynamic()) { 802 return bridge == null ? null : bridge.getInstance(); 803 } else { 804 return bridge; 805 } 806 } 807 808 815 public void putBridge(String namespaceURI, String localName, Bridge bridge) { 816 if (!(namespaceURI.equals(bridge.getNamespaceURI()) 818 && localName.equals(bridge.getLocalName()))) { 819 throw new Error ("Invalid Bridge: "+ 820 namespaceURI+"/"+bridge.getNamespaceURI()+" "+ 821 localName+"/"+bridge.getLocalName()+" "+ 822 bridge.getClass()); 823 } 824 if (namespaceURIMap == null) { 826 namespaceURIMap = new HashMap (); 827 } 828 namespaceURI = ((namespaceURI == null)? "" : namespaceURI); 829 HashMap localNameMap = (HashMap ) namespaceURIMap.get(namespaceURI); 830 if (localNameMap == null) { 831 localNameMap = new HashMap (); 832 namespaceURIMap.put(namespaceURI, localNameMap); 833 } 834 localNameMap.put(localName, bridge); 835 } 836 837 843 public void putBridge(Bridge bridge) { 844 putBridge(bridge.getNamespaceURI(), bridge.getLocalName(), bridge); 845 } 846 847 854 public void removeBr
|