1 18 package org.apache.batik.bridge; 19 20 import java.awt.RenderingHints ; 21 import java.awt.Shape ; 22 import java.awt.color.ColorSpace ; 23 import java.awt.color.ICC_Profile ; 24 import java.awt.geom.AffineTransform ; 25 import java.awt.geom.Rectangle2D ; 26 import java.io.BufferedInputStream ; 27 import java.io.InputStream ; 28 import java.io.IOException ; 29 import java.util.ArrayList ; 30 import java.util.List ; 31 32 import org.apache.batik.css.engine.CSSEngine; 33 import org.apache.batik.css.engine.SVGCSSEngine; 34 import org.apache.batik.dom.svg.SVGOMDocument; 35 import org.apache.batik.dom.svg.SVGOMElement; 36 import org.apache.batik.dom.svg.XMLBaseSupport; 37 import org.apache.batik.dom.util.XLinkSupport; 38 import org.apache.batik.ext.awt.color.ICCColorSpaceExt; 39 import org.apache.batik.ext.awt.image.renderable.ClipRable8Bit; 40 import org.apache.batik.ext.awt.image.renderable.Filter; 41 import org.apache.batik.ext.awt.image.spi.ImageTagRegistry; 42 import org.apache.batik.gvt.CanvasGraphicsNode; 43 import org.apache.batik.gvt.CompositeGraphicsNode; 44 import org.apache.batik.gvt.GraphicsNode; 45 import org.apache.batik.gvt.ImageNode; 46 import org.apache.batik.gvt.RasterImageNode; 47 import org.apache.batik.gvt.ShapeNode; 48 import org.apache.batik.util.ParsedURL; 49 import org.apache.batik.util.MimeTypeConstants; 50 import org.w3c.dom.Document ; 51 import org.w3c.dom.Element ; 52 import org.w3c.dom.Node ; 53 import org.w3c.dom.events.DocumentEvent ; 54 import org.w3c.dom.events.Event ; 55 import org.w3c.dom.events.EventListener ; 56 import org.w3c.dom.events.EventTarget ; 57 import org.w3c.dom.events.MouseEvent ; 58 import org.w3c.dom.events.MutationEvent ; 59 import org.w3c.dom.svg.SVGDocument; 60 import org.w3c.dom.svg.SVGSVGElement; 61 62 68 public class SVGImageElementBridge extends AbstractGraphicsNodeBridge { 69 70 protected SVGDocument imgDocument; 71 protected EventListener listener = null; 72 protected BridgeContext subCtx = null; 73 protected boolean hitCheckChildren = false; 74 77 public SVGImageElementBridge() {} 78 79 82 public String getLocalName() { 83 return SVG_IMAGE_TAG; 84 } 85 86 89 public Bridge getInstance() { 90 return new SVGImageElementBridge(); 91 } 92 93 101 public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) { 102 ImageNode imageNode = (ImageNode)super.createGraphicsNode(ctx, e); 103 if (imageNode == null) { 104 return null; 105 } 106 107 hitCheckChildren = false; 108 GraphicsNode node = buildImageGraphicsNode(ctx,e); 109 110 if (node == null) { 111 String uriStr = XLinkSupport.getXLinkHref(e); 112 throw new BridgeException(e, ERR_URI_IMAGE_INVALID, 113 new Object [] {uriStr}); 114 } 115 116 imageNode.setImage(node); 117 imageNode.setHitCheckChildren(hitCheckChildren); 118 119 RenderingHints hints = null; 121 hints = CSSUtilities.convertImageRendering(e, hints); 122 hints = CSSUtilities.convertColorRendering(e, hints); 123 if (hints != null) 124 imageNode.setRenderingHints(hints); 125 126 return imageNode; 127 } 128 129 140 protected GraphicsNode buildImageGraphicsNode 141 (BridgeContext ctx, Element e){ 142 143 String uriStr = XLinkSupport.getXLinkHref(e); 145 if (uriStr.length() == 0) { 146 throw new BridgeException(e, ERR_ATTRIBUTE_MISSING, 147 new Object [] {"xlink:href"}); 148 } 149 if (uriStr.indexOf('#') != -1) { 150 throw new BridgeException(e, ERR_ATTRIBUTE_VALUE_MALFORMED, 151 new Object [] {"xlink:href", uriStr}); 152 } 153 154 String baseURI = XMLBaseSupport.getCascadedXMLBase(e); 156 ParsedURL purl; 157 if (baseURI == null) 158 purl = new ParsedURL(uriStr); 159 else 160 purl = new ParsedURL(baseURI, uriStr); 161 162 return createImageGraphicsNode(ctx, e, purl); 163 } 164 165 protected GraphicsNode createImageGraphicsNode(BridgeContext ctx, 166 Element e, 167 ParsedURL purl) 168 { 169 Rectangle2D bounds = getImageBounds(ctx, e); 170 if ((bounds.getWidth() == 0) || (bounds.getHeight() == 0)) { 171 ShapeNode sn = new ShapeNode(); 172 sn.setShape(bounds); 173 return sn; 174 } 175 176 SVGDocument svgDoc = (SVGDocument)e.getOwnerDocument(); 177 String docURL = svgDoc.getURL(); 178 ParsedURL pDocURL = null; 179 if (docURL != null) 180 pDocURL = new ParsedURL(docURL); 181 182 UserAgent userAgent = ctx.getUserAgent(); 183 184 try { 185 userAgent.checkLoadExternalResource(purl, pDocURL); 186 } catch (SecurityException ex) { 187 throw new BridgeException(e, ERR_URI_UNSECURE, 188 new Object [] {purl}); 189 } 190 191 DocumentLoader loader = ctx.getDocumentLoader(); 192 ImageTagRegistry reg = ImageTagRegistry.getRegistry(); 193 ICCColorSpaceExt colorspace = extractColorSpace(e, ctx); 194 { 195 199 try { 200 201 Document doc = loader.checkCache(purl.toString()); 202 if (doc != null) { 203 imgDocument = (SVGDocument)doc; 204 return createSVGImageNode(ctx, e, imgDocument); 205 } 206 } catch (BridgeException ex) { 207 throw ex; 208 } catch (Exception ex) { 209 210 } 211 212 213 Filter img = reg.checkCache(purl, colorspace); 214 if (img != null) { 215 return createRasterImageNode(ctx, e, img); 216 } 217 } 218 219 226 ProtectedStream reference = null; 227 try { 228 reference = openStream(e, purl); 229 } catch (SecurityException ex) { 230 throw new BridgeException(e, ERR_URI_UNSECURE, 231 new Object [] {purl}); 232 } catch (IOException ioe) { 233 return createBrokenImageNode(ctx, e, purl.toString()); 234 } 235 236 { 237 243 Filter img = reg.readURL(reference, purl, colorspace, 244 false, false); 245 if (img != null) { 246 return createRasterImageNode(ctx, e, img); 248 } 249 } 250 251 try { 252 reference.retry(); 254 } catch (IOException ioe) { 255 try { 256 reference = openStream(e, purl); 258 } catch (IOException ioe2) { 259 return createBrokenImageNode(ctx, e, purl.toString()); 261 } 262 } 263 264 try { 265 268 Document doc = loader.loadDocument(purl.toString(), reference); 269 imgDocument = (SVGDocument)doc; 270 return createSVGImageNode(ctx, e, imgDocument); 271 } catch (BridgeException ex) { 272 throw ex; 273 } catch (SecurityException ex) { 274 throw new BridgeException(e, ERR_URI_UNSECURE, 275 new Object [] {purl}); 276 } catch (Exception ex) { 277 278 } 280 281 try { 282 reference.retry(); 283 } catch (IOException ioe) { 284 try { 285 reference = openStream(e, purl); 287 } catch (IOException ioe2) { 288 return createBrokenImageNode(ctx, e, purl.toString()); 289 } 290 } 291 292 try { 293 Filter img = reg.readURL(reference, purl, colorspace, 297 true, true); 298 if (img != null) { 299 return createRasterImageNode(ctx, e, img); 301 } 302 } finally { 303 reference.release(); 304 } 305 return null; 306 } 307 308 static public class ProtectedStream extends BufferedInputStream { 309 final static int BUFFER_SIZE = 8192; 310 ProtectedStream(InputStream is) { 311 super(is, BUFFER_SIZE); 312 super.mark(BUFFER_SIZE); } 314 ProtectedStream(InputStream is, int size) { 315 super(is, size); 316 super.mark(size); } 318 319 public boolean markSupported() { 320 return false; 321 } 322 public void mark(int sz){ 323 } 324 public void reset() throws IOException { 325 throw new IOException ("Reset unsupported"); 326 } 327 328 public void retry() throws IOException { 329 super.reset(); 330 } 331 332 public void close() throws IOException { 333 334 } 335 336 public void release() { 337 try { 338 super.close(); 339 } catch (IOException ioe) { 340 } 342 } 343 } 344 345 protected ProtectedStream openStream(Element e, ParsedURL purl) 346 throws IOException { 347 List mimeTypes = new ArrayList 348 (ImageTagRegistry.getRegistry().getRegisteredMimeTypes()); 349 mimeTypes.add(MimeTypeConstants.MIME_TYPES_SVG); 350 InputStream reference = purl.openStream(mimeTypes.iterator()); 351 return new ProtectedStream(reference); 352 } 353 354 357 protected GraphicsNode instantiateGraphicsNode() { 358 return new ImageNode(); 359 } 360 361 364 public boolean isComposite() { 365 return false; 366 } 367 368 370 376 protected void initializeDynamicSupport(BridgeContext ctx, 377 Element e, 378 GraphicsNode node) { 379 if (!ctx.isInteractive()) 380 return; 381 382 ImageNode imgNode = (ImageNode)node; 385 ctx.bind(e, node); 386 387 if (ctx.isDynamic()) { 388 this.e = e; 390 this.node = node; 391 this.ctx = ctx; 392 ((SVGOMElement)e).setSVGContext(this); 393 } 394 } 395 396 398 401 public void handleDOMAttrModifiedEvent(MutationEvent evt) { 402 403 String attrName = evt.getAttrName(); 404 Node evtNode = evt.getRelatedNode(); 405 406 if (attrName.equals(SVG_X_ATTRIBUTE) || 407 attrName.equals(SVG_Y_ATTRIBUTE) || 408 attrName.equals(SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE)){ 409 updateImageBounds(); 410 } else if (( XLinkSupport.XLINK_NAMESPACE_URI.equals 411 (evtNode.getNamespaceURI()) ) 412 && SVG_HREF_ATTRIBUTE.equals(evtNode.getLocalName()) ){ 413 rebuildImageNode(); 414 } else if(attrName.equals(SVG_WIDTH_ATTRIBUTE) || 415 attrName.equals(SVG_HEIGHT_ATTRIBUTE)) { 416 float oldV = 0, newV=0; 417 String s = evt.getPrevValue(); 418 UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, e); 419 420 if (s.length() != 0) { 421 oldV = UnitProcessor.svgHorizontalCoordinateToUserSpace 422 (s, attrName, uctx); 423 } 424 s = evt.getNewValue(); 425 if (s.length() != 0) { 426 newV = UnitProcessor.svgHorizontalCoordinateToUserSpace 427 (s, attrName, uctx); 428 } 429 if (oldV == newV) return; 430 431 if ((oldV == 0) || (newV == 0)) 432 rebuildImageNode(); 433 else 434 updateImageBounds(); 435 } else { 436 super.handleDOMAttrModifiedEvent(evt); 437 } 438 } 439 440 protected void updateImageBounds() { 441 Rectangle2D bounds = getImageBounds(ctx, e); 443 GraphicsNode imageNode = ((ImageNode)node).getImage(); 444 float [] vb = null; 445 if (imageNode instanceof RasterImageNode) { 446 Rectangle2D imgBounds = 448 ((RasterImageNode)imageNode).getImageBounds(); 449 vb = new float[4]; 453 vb[0] = 0; vb[1] = 0; vb[2] = (float)imgBounds.getWidth(); vb[3] = (float)imgBounds.getHeight(); } else { 458 if (imgDocument != null) { 459 Element svgElement = imgDocument.getRootElement(); 460 String viewBox = svgElement.getAttributeNS 461 (null, SVG_VIEW_BOX_ATTRIBUTE); 462 vb = ViewBox.parseViewBoxAttribute(e, viewBox); 463 } 464 } 465 if (imageNode != null) { 466 initializeViewport(ctx, e, imageNode, vb, bounds); 470 } 471 472 } 473 474 protected void rebuildImageNode() { 475 if ((imgDocument != null) && (listener != null)) { 477 EventTarget tgt = (EventTarget )imgDocument.getRootElement(); 478 479 tgt.removeEventListener(SVG_EVENT_CLICK, listener, false); 480 tgt.removeEventListener(SVG_EVENT_KEYDOWN, listener, false); 481 tgt.removeEventListener(SVG_EVENT_KEYPRESS, listener, false); 482 tgt.removeEventListener(SVG_EVENT_KEYUP, listener, false); 483 tgt.removeEventListener(SVG_EVENT_MOUSEDOWN, listener, false); 484 tgt.removeEventListener(SVG_EVENT_MOUSEMOVE, listener, false); 485 tgt.removeEventListener(SVG_EVENT_MOUSEOUT, listener, false); 486 tgt.removeEventListener(SVG_EVENT_MOUSEOVER, listener, false); 487 tgt.removeEventListener(SVG_EVENT_MOUSEUP, listener, false); 488 listener = null; 489 } 490 491 if (imgDocument != null) { 492 SVGSVGElement svgElement = imgDocument.getRootElement(); 493 disposeTree(svgElement); 494 } 495 496 imgDocument = null; 497 subCtx = null; 498 499 GraphicsNode inode = buildImageGraphicsNode(ctx,e); 501 502 ImageNode imgNode = (ImageNode)node; 503 imgNode.setImage(inode); 504 505 if (inode == null) { 506 String uriStr = XLinkSupport.getXLinkHref(e); 507 throw new BridgeException(e, ERR_URI_IMAGE_INVALID, 508 new Object [] {uriStr}); 509 } 510 } 511 512 515 protected void handleCSSPropertyChanged(int property) { 516 switch(property) { 517 case SVGCSSEngine.IMAGE_RENDERING_INDEX: 518 case SVGCSSEngine.COLOR_INTERPOLATION_INDEX: 519 RenderingHints hints = CSSUtilities.convertImageRendering(e, null); 520 hints = CSSUtilities.convertColorRendering(e, hints); 521 if (hints != null) { 522 node.setRenderingHints(hints); 523 } 524 break; 525 default: 526 super.handleCSSPropertyChanged(property); 527 } 528 } 529 530 532 540 protected GraphicsNode createRasterImageNode(BridgeContext ctx, 541 Element e, 542 Filter img) { 543 Rectangle2D bounds = getImageBounds(ctx, e); 544 if ((bounds.getWidth() == 0) || (bounds.getHeight() == 0)) { 545 ShapeNode sn = new ShapeNode(); 546 sn.setShape(bounds); 547 return sn; 548 } 549 Object obj = img.getProperty 550 (SVGBrokenLinkProvider.SVG_BROKEN_LINK_DOCUMENT_PROPERTY); 551 if ((obj != null) && (obj instanceof SVGDocument)) { 552 SVGOMDocument doc = (SVGOMDocument)obj; 554 return createSVGImageNode(ctx, e, doc); 555 } 556 557 RasterImageNode node = new RasterImageNode(); 558 node.setImage(img); 559 Rectangle2D imgBounds = img.getBounds2D(); 560 561 float [] vb = new float[4]; 564 vb[0] = 0; vb[1] = 0; vb[2] = (float)imgBounds.getWidth(); vb[3] = (float)imgBounds.getHeight(); 569 initializeViewport(ctx, e, node, vb, bounds); 572 573 return node; 574 } 575 576 583 protected GraphicsNode createSVGImageNode(BridgeContext ctx, 584 Element e, 585 SVGDocument imgDocument) { 586 CSSEngine eng = ((SVGOMDocument)imgDocument).getCSSEngine(); 587 if (eng != null) { 588 subCtx = (BridgeContext)eng.getCSSContext(); 589 } else { 590 subCtx = new BridgeContext(ctx.getUserAgent(), 591 ctx.getDocumentLoader()); 592 subCtx.setGVTBuilder(ctx.getGVTBuilder()); 593 subCtx.setDocument(imgDocument); 594 subCtx.initializeDocument(imgDocument); 595 } 596 597 CompositeGraphicsNode result = new CompositeGraphicsNode(); 598 Rectangle2D bounds = getImageBounds(ctx, e); 601 602 if ((bounds.getWidth() == 0) || (bounds.getHeight() == 0)) { 603 ShapeNode sn = new ShapeNode(); 604 sn.setShape(bounds); 605 result.getChildren().add(sn); 606 return result; 607 } 608 609 Rectangle2D r = CSSUtilities.convertEnableBackground(e); 610 if (r != null) { 611 result.setBackgroundEnable(r); 612 } 613 614 SVGSVGElement svgElement = imgDocument.getRootElement(); 615 CanvasGraphicsNode node; 616 node = (CanvasGraphicsNode)subCtx.getGVTBuilder().build 617 (subCtx, svgElement); 618 619 if (eng == null) subCtx.addUIEventListeners(imgDocument); 621 622 node.setClip(null); 626 node.setViewingTransform(new AffineTransform ()); 630 result.getChildren().add(node); 631 632 String viewBox = 635 svgElement.getAttributeNS(null, SVG_VIEW_BOX_ATTRIBUTE); 636 float [] vb = ViewBox.parseViewBoxAttribute(e, viewBox); 637 638 initializeViewport(ctx, e, result, vb, bounds); 639 640 if (ctx.isInteractive()) { 644 listener = new ForwardEventListener(svgElement, e); 645 EventTarget tgt = (EventTarget )svgElement; 646 647 tgt.addEventListener(SVG_EVENT_CLICK, listener, false); 648 subCtx.storeEventListener(tgt, SVG_EVENT_CLICK, listener, false); 649 650 tgt.addEventListener(SVG_EVENT_KEYDOWN, listener, false); 651 subCtx.storeEventListener(tgt, SVG_EVENT_KEYDOWN, listener, false); 652 653 tgt.addEventListener(SVG_EVENT_KEYPRESS, listener, false); 654 subCtx.storeEventListener(tgt, SVG_EVENT_KEYPRESS, listener, false); 655 656 tgt.addEventListener(SVG_EVENT_KEYUP, listener, false); 657 subCtx.storeEventListener(tgt, SVG_EVENT_KEYUP, listener, false); 658 659 tgt.addEventListener(SVG_EVENT_MOUSEDOWN, listener, false); 660 subCtx.storeEventListener(tgt, SVG_EVENT_MOUSEDOWN, listener,false); 661 662 tgt.addEventListener(SVG_EVENT_MOUSEMOVE, listener, false); 663 subCtx.storeEventListener(tgt, SVG_EVENT_MOUSEMOVE, listener,false); 664 665 tgt.addEventListener(SVG_EVENT_MOUSEOUT, listener, false); 666 subCtx.storeEventListener(tgt, SVG_EVENT_MOUSEOUT, listener, false); 667 668 tgt.addEventListener(SVG_EVENT_MOUSEOVER, listener, false); 669 subCtx.storeEventListener(tgt, SVG_EVENT_MOUSEOVER, listener,false); 670 671 tgt.addEventListener(SVG_EVENT_MOUSEUP, listener, false); 672 subCtx.storeEventListener(tgt, SVG_EVENT_MOUSEUP, listener, false); 673 } 674 675 return result; 676 } 677 678 public void dispose() { 679 if ((imgDocument != null) && (listener != null)) { 680 EventTarget tgt = (EventTarget )imgDocument.getRootElement(); 681 682 tgt.removeEventListener(SVG_EVENT_CLICK, listener, false); 683 tgt.removeEventListener(SVG_EVENT_KEYDOWN, listener, false); 684 tgt.removeEventListener(SVG_EVENT_KEYPRESS, listener, false); 685 tgt.removeEventListener(SVG_EVENT_KEYUP, listener, false); 686 tgt.removeEventListener(SVG_EVENT_MOUSEDOWN, listener, false); 687 tgt.removeEventListener(SVG_EVENT_MOUSEMOVE, listener, false); 688 tgt.removeEventListener(SVG_EVENT_MOUSEOUT, listener, false); 689 tgt.removeEventListener(SVG_EVENT_MOUSEOVER, listener, false); 690 tgt.removeEventListener(SVG_EVENT_MOUSEUP, listener, false); 691 listener = null; 692 } 693 694 if (imgDocument != null) { 695 SVGSVGElement svgElement = imgDocument.getRootElement(); 696 disposeTree(svgElement); 697 imgDocument = null; 698 subCtx = null; 699 } 700 super.dispose(); 701 702 } 703 707 protected static class ForwardEventListener implements EventListener { 708 709 712 protected Element svgElement; 713 714 717 protected Element imgElement; 718 719 722 public ForwardEventListener(Element svgElement, Element imgElement) { 723 this.svgElement = svgElement; 724 this.imgElement = imgElement; 725 } 726 727 public void handleEvent(Event e) { 728 MouseEvent evt = (MouseEvent ) e; 729 MouseEvent newMouseEvent = (MouseEvent ) 730 ((DocumentEvent )imgElement.getOwnerDocument()).createEvent("MouseEvents"); 732 733 newMouseEvent.initMouseEvent(evt.getType(), 734 evt.getBubbles(), 735 evt.getCancelable(), 736 evt.getView(), 737 evt.getDetail(), 738 evt.getScreenX(), 739 evt.getScreenY(), 740 evt.getClientX(), 741 evt.getClientY(), 742 evt.getCtrlKey(), 743 evt.getAltKey(), 744 evt.getShiftKey(), 745 evt.getMetaKey(), 746 evt.getButton(), 747 (EventTarget )imgElement); 748 ((EventTarget )imgElement).dispatchEvent(newMouseEvent); 749 } 750 } 751 752 764 protected static void initializeViewport(BridgeContext ctx, 765 Element e, 766 GraphicsNode node, 767 float [] vb, 768 Rectangle2D bounds) { 769 770 float x = (float)bounds.getX(); 771 float y = (float)bounds.getY(); 772 float w = (float)bounds.getWidth(); 773 float h = (float)bounds.getHeight(); 774 775 AffineTransform at 776 = ViewBox.getPreserveAspectRatioTransform(e, vb, w, h); 777 at.preConcatenate(AffineTransform.getTranslateInstance(x, y)); 778 node.setTransform(at); 779 780 Shape clip = null; 782 if (CSSUtilities.convertOverflow(e)) { float [] offsets = CSSUtilities.convertClip(e); 784 if (offsets == null) { clip = new Rectangle2D.Float (x, y, w, h); 786 } else { clip = new Rectangle2D.Float (x+offsets[3], 792 y+offsets[0], 793 w-offsets[1]-offsets[3], 794 h-offsets[2]-offsets[0]); 795 } 796 } 797 798 if (clip != null) { 799 try { 800 at = at.createInverse(); Filter filter = node.getGraphicsNodeRable(true); 802 clip = at.createTransformedShape(clip); 803 node.setClip(new ClipRable8Bit(filter, clip)); 804 } catch (java.awt.geom.NoninvertibleTransformException ex) {} 805 } 806 } 807 808 815 protected static ICCColorSpaceExt extractColorSpace(Element element, 816 BridgeContext ctx) { 817 818 String colorProfileProperty = CSSUtilities.getComputedStyle 819 (element, SVGCSSEngine.COLOR_PROFILE_INDEX).getStringValue(); 820 821 ICCColorSpaceExt colorSpace = null; 823 if (CSS_SRGB_VALUE.equalsIgnoreCase(colorProfileProperty)) { 824 825 colorSpace = new ICCColorSpaceExt 826 (ICC_Profile.getInstance(ColorSpace.CS_sRGB), 827 ICCColorSpaceExt.AUTO); 828 829 } else if (!CSS_AUTO_VALUE.equalsIgnoreCase(colorProfileProperty) 830 && !"".equalsIgnoreCase(colorProfileProperty)){ 831 832 SVGColorProfileElementBridge profileBridge = 834 (SVGColorProfileElementBridge) ctx.getBridge 835 (SVG_NAMESPACE_URI, SVG_COLOR_PROFILE_TAG); 836 if (profileBridge != null) { 837 colorSpace = profileBridge.createICCColorSpaceExt 838 (ctx, element, colorProfileProperty); 839 840 } 841 } 842 return colorSpace; 843 } 844 845 851 protected static 852 Rectangle2D getImageBounds(BridgeContext ctx, Element element) { 853 854 UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, element); 855 856 String s = element.getAttributeNS(null, SVG_X_ATTRIBUTE); 858 float x = 0; 859 if (s.length() != 0) { 860 x = UnitProcessor.svgHorizontalCoordinateToUserSpace 861 (s, SVG_X_ATTRIBUTE, uctx); 862 } 863 864 s = element.getAttributeNS(null, SVG_Y_ATTRIBUTE); 866 float y = 0; 867 if (s.length() != 0) { 868 y = UnitProcessor.svgVerticalCoordinateToUserSpace 869 (s, SVG_Y_ATTRIBUTE, uctx); 870 } 871 872 s = element.getAttributeNS(null, SVG_WIDTH_ATTRIBUTE); 874 float w; 875 if (s.length() == 0) { 876 throw new BridgeException(element, ERR_ATTRIBUTE_MISSING, 877 new Object [] {SVG_WIDTH_ATTRIBUTE}); 878 } else { 879 w = UnitProcessor.svgHorizontalLengthToUserSpace 880 (s, SVG_WIDTH_ATTRIBUTE, uctx); 881 } 882 883 s = element.getAttributeNS(null, SVG_HEIGHT_ATTRIBUTE); 885 float h; 886 if (s.length() == 0) { 887 throw new BridgeException(element, ERR_ATTRIBUTE_MISSING, 888 new Object [] {SVG_HEIGHT_ATTRIBUTE}); 889 } else { 890 h = UnitProcessor.svgVerticalLengthToUserSpace 891 (s, SVG_HEIGHT_ATTRIBUTE, uctx); 892 } 893 894 return new Rectangle2D.Float (x, y, w, h); 895 } 896 897 GraphicsNode createBrokenImageNode 898 (BridgeContext ctx, Element e, String uri) { 899 900 String lname = "<Unknown Element>"; 901 SVGDocument doc = null; 902 if (e != null) { 903 doc = (SVGDocument)e.getOwnerDocument(); 904 lname = e.getLocalName(); 905 } 906 String docUri; 907 if (doc == null) docUri = "<Unknown Document>"; 908 else docUri = doc.getURL(); 909 int line = ctx.getDocumentLoader().getLineNumber(e); 910 Object [] fullparams = new Object [4]; 911 fullparams[0] = docUri; 912 fullparams[1] = new Integer (line); 913 fullparams[2] = lname; 914 fullparams[3] = uri; 915 916 SVGDocument blDoc = brokenLinkProvider.getBrokenLinkDocument 917 (this, ERR_URI_IO, fullparams); 918 hitCheckChildren = true; 919 return createSVGImageNode(ctx, e, blDoc); 920 } 921 922 923 static SVGBrokenLinkProvider brokenLinkProvider 924 = new SVGBrokenLinkProvider(); 925 static { 926 ImageTagRegistry.setBrokenLinkProvider(brokenLinkProvider); 927 } 928 } 929 | Popular Tags |