Source Code Cross Referenced for SVGImageElementBridge.java in  » Graphic-Library » batik » org » apache » batik » bridge » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Graphic Library » batik » org.apache.batik.bridge 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:
0003:           Licensed to the Apache Software Foundation (ASF) under one or more
0004:           contributor license agreements.  See the NOTICE file distributed with
0005:           this work for additional information regarding copyright ownership.
0006:           The ASF licenses this file to You under the Apache License, Version 2.0
0007:           (the "License"); you may not use this file except in compliance with
0008:           the License.  You may obtain a copy of the License at
0009:
0010:               http://www.apache.org/licenses/LICENSE-2.0
0011:
0012:           Unless required by applicable law or agreed to in writing, software
0013:           distributed under the License is distributed on an "AS IS" BASIS,
0014:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0015:           See the License for the specific language governing permissions and
0016:           limitations under the License.
0017:
0018:         */
0019:        package org.apache.batik.bridge;
0020:
0021:        import java.awt.RenderingHints;
0022:        import java.awt.Shape;
0023:        import java.awt.color.ColorSpace;
0024:        import java.awt.color.ICC_Profile;
0025:        import java.awt.geom.AffineTransform;
0026:        import java.awt.geom.Rectangle2D;
0027:        import java.io.BufferedInputStream;
0028:        import java.io.InputStream;
0029:        import java.io.InterruptedIOException;
0030:        import java.io.IOException;
0031:        import java.util.ArrayList;
0032:        import java.util.List;
0033:
0034:        import org.apache.batik.css.engine.CSSEngine;
0035:        import org.apache.batik.css.engine.SVGCSSEngine;
0036:        import org.apache.batik.dom.AbstractNode;
0037:        import org.apache.batik.dom.events.DOMMouseEvent;
0038:        import org.apache.batik.dom.events.NodeEventTarget;
0039:        import org.apache.batik.dom.svg.AnimatedLiveAttributeValue;
0040:        import org.apache.batik.dom.svg.LiveAttributeException;
0041:        import org.apache.batik.dom.svg.SVGOMDocument;
0042:        import org.apache.batik.dom.svg.SVGOMElement;
0043:        import org.apache.batik.ext.awt.color.ICCColorSpaceExt;
0044:        import org.apache.batik.ext.awt.image.renderable.ClipRable8Bit;
0045:        import org.apache.batik.ext.awt.image.renderable.Filter;
0046:        import org.apache.batik.ext.awt.image.spi.BrokenLinkProvider;
0047:        import org.apache.batik.ext.awt.image.spi.ImageTagRegistry;
0048:        import org.apache.batik.gvt.CanvasGraphicsNode;
0049:        import org.apache.batik.gvt.CompositeGraphicsNode;
0050:        import org.apache.batik.gvt.GraphicsNode;
0051:        import org.apache.batik.gvt.ImageNode;
0052:        import org.apache.batik.gvt.RasterImageNode;
0053:        import org.apache.batik.gvt.ShapeNode;
0054:        import org.apache.batik.util.HaltingThread;
0055:        import org.apache.batik.util.MimeTypeConstants;
0056:        import org.apache.batik.util.ParsedURL;
0057:        import org.apache.batik.util.XMLConstants;
0058:
0059:        import org.w3c.dom.Document;
0060:        import org.w3c.dom.Element;
0061:        import org.w3c.dom.events.DocumentEvent;
0062:        import org.w3c.dom.events.Event;
0063:        import org.w3c.dom.events.EventListener;
0064:        import org.w3c.dom.events.EventTarget;
0065:        import org.w3c.dom.svg.SVGAnimatedPreserveAspectRatio;
0066:        import org.w3c.dom.svg.SVGDocument;
0067:        import org.w3c.dom.svg.SVGImageElement;
0068:        import org.w3c.dom.svg.SVGSVGElement;
0069:
0070:        /**
0071:         * Bridge class for the <image> element.
0072:         *
0073:         * @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a>
0074:         * @version $Id: SVGImageElementBridge.java 501922 2007-01-31 17:47:47Z dvholten $
0075:         */
0076:        public class SVGImageElementBridge extends AbstractGraphicsNodeBridge {
0077:
0078:            protected SVGDocument imgDocument;
0079:            protected EventListener listener = null;
0080:            protected BridgeContext subCtx = null;
0081:            protected boolean hitCheckChildren = false;
0082:
0083:            /**
0084:             * Constructs a new bridge for the &lt;image> element.
0085:             */
0086:            public SVGImageElementBridge() {
0087:            }
0088:
0089:            /**
0090:             * Returns 'image'.
0091:             */
0092:            public String getLocalName() {
0093:                return SVG_IMAGE_TAG;
0094:            }
0095:
0096:            /**
0097:             * Returns a new instance of this bridge.
0098:             */
0099:            public Bridge getInstance() {
0100:                return new SVGImageElementBridge();
0101:            }
0102:
0103:            /**
0104:             * Creates a graphics node using the specified BridgeContext and for the
0105:             * specified element.
0106:             *
0107:             * @param ctx the bridge context to use
0108:             * @param e the element that describes the graphics node to build
0109:             * @return a graphics node that represents the specified element
0110:             */
0111:            public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) {
0112:                ImageNode imageNode = (ImageNode) super .createGraphicsNode(ctx,
0113:                        e);
0114:                if (imageNode == null) {
0115:                    return null;
0116:                }
0117:
0118:                associateSVGContext(ctx, e, imageNode);
0119:
0120:                hitCheckChildren = false;
0121:                GraphicsNode node = buildImageGraphicsNode(ctx, e);
0122:
0123:                if (node == null) {
0124:                    SVGImageElement ie = (SVGImageElement) e;
0125:                    String uriStr = ie.getHref().getAnimVal();
0126:                    throw new BridgeException(ctx, e, ERR_URI_IMAGE_INVALID,
0127:                            new Object[] { uriStr });
0128:                }
0129:
0130:                imageNode.setImage(node);
0131:                imageNode.setHitCheckChildren(hitCheckChildren);
0132:
0133:                // 'image-rendering' and 'color-rendering'
0134:                RenderingHints hints = null;
0135:                hints = CSSUtilities.convertImageRendering(e, hints);
0136:                hints = CSSUtilities.convertColorRendering(e, hints);
0137:                if (hints != null)
0138:                    imageNode.setRenderingHints(hints);
0139:
0140:                return imageNode;
0141:            }
0142:
0143:            /**
0144:             * Create a Graphics node according to the
0145:             * resource pointed by the href : RasterImageNode
0146:             * for bitmaps, CompositeGraphicsNode for svg files.
0147:             *
0148:             * @param ctx : the bridge context to use
0149:             * @param e the element that describes the graphics node to build
0150:             *
0151:             * @return the graphic node that represent the resource
0152:             *  pointed by the reference
0153:             */
0154:            protected GraphicsNode buildImageGraphicsNode(BridgeContext ctx,
0155:                    Element e) {
0156:
0157:                SVGImageElement ie = (SVGImageElement) e;
0158:
0159:                // 'xlink:href' attribute - required
0160:                String uriStr = ie.getHref().getAnimVal();
0161:                if (uriStr.length() == 0) {
0162:                    throw new BridgeException(ctx, e, ERR_ATTRIBUTE_MISSING,
0163:                            new Object[] { "xlink:href" });
0164:                }
0165:                if (uriStr.indexOf('#') != -1) {
0166:                    throw new BridgeException(ctx, e,
0167:                            ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {
0168:                                    "xlink:href", uriStr });
0169:                }
0170:
0171:                // Build the URL.
0172:                String baseURI = AbstractNode.getBaseURI(e);
0173:                ParsedURL purl;
0174:                if (baseURI == null) {
0175:                    purl = new ParsedURL(uriStr);
0176:                } else {
0177:                    purl = new ParsedURL(baseURI, uriStr);
0178:                }
0179:
0180:                return createImageGraphicsNode(ctx, e, purl);
0181:            }
0182:
0183:            protected GraphicsNode createImageGraphicsNode(BridgeContext ctx,
0184:                    Element e, ParsedURL purl) {
0185:                Rectangle2D bounds = getImageBounds(ctx, e);
0186:                if ((bounds.getWidth() == 0) || (bounds.getHeight() == 0)) {
0187:                    ShapeNode sn = new ShapeNode();
0188:                    sn.setShape(bounds);
0189:                    return sn;
0190:                }
0191:
0192:                SVGDocument svgDoc = (SVGDocument) e.getOwnerDocument();
0193:                String docURL = svgDoc.getURL();
0194:                ParsedURL pDocURL = null;
0195:                if (docURL != null)
0196:                    pDocURL = new ParsedURL(docURL);
0197:
0198:                UserAgent userAgent = ctx.getUserAgent();
0199:
0200:                try {
0201:                    userAgent.checkLoadExternalResource(purl, pDocURL);
0202:                } catch (SecurityException secEx) {
0203:                    throw new BridgeException(ctx, e, secEx, ERR_URI_UNSECURE,
0204:                            new Object[] { purl });
0205:                }
0206:
0207:                DocumentLoader loader = ctx.getDocumentLoader();
0208:                ImageTagRegistry reg = ImageTagRegistry.getRegistry();
0209:                ICCColorSpaceExt colorspace = extractColorSpace(e, ctx);
0210:                {
0211:                    /**
0212:                     *  Before we open the URL we see if we have the
0213:                     *  URL already cached and parsed
0214:                     */
0215:                    try {
0216:                        /* Check the document loader cache */
0217:                        Document doc = loader.checkCache(purl.toString());
0218:                        if (doc != null) {
0219:                            imgDocument = (SVGDocument) doc;
0220:                            return createSVGImageNode(ctx, e, imgDocument);
0221:                        }
0222:                    } catch (BridgeException ex) {
0223:                        throw ex;
0224:                    } catch (Exception ex) {
0225:                        /* Nothing to do */
0226:                    }
0227:
0228:                    /* Check the ImageTagRegistry Cache */
0229:                    Filter img = reg.checkCache(purl, colorspace);
0230:                    if (img != null) {
0231:                        return createRasterImageNode(ctx, e, img, purl);
0232:                    }
0233:                }
0234:
0235:                /* The Protected Stream ensures that the stream doesn't
0236:                 * get closed unless we want it to. It is also based on
0237:                 * a Buffered Reader so in general we can mark the start
0238:                 * and reset rather than reopening the stream.  Finally
0239:                 * it hides the mark/reset methods so only we get to
0240:                 * use them.
0241:                 */
0242:                ProtectedStream reference = null;
0243:                try {
0244:                    reference = openStream(e, purl);
0245:                } catch (SecurityException secEx) {
0246:                    throw new BridgeException(ctx, e, secEx, ERR_URI_UNSECURE,
0247:                            new Object[] { purl });
0248:                } catch (IOException ioe) {
0249:                    return createBrokenImageNode(ctx, e, purl.toString(), ioe
0250:                            .getLocalizedMessage());
0251:                }
0252:
0253:                {
0254:                    /**
0255:                     * First see if we can id the file as a Raster via magic
0256:                     * number.  This is probably the fastest mechanism.
0257:                     * We tell the registry what the source purl is but we
0258:                     * tell it not to open that url.
0259:                     */
0260:                    Filter img = reg.readURL(reference, purl, colorspace,
0261:                            false, false);
0262:                    if (img != null) {
0263:                        // It's a bouncing baby Raster...
0264:                        return createRasterImageNode(ctx, e, img, purl);
0265:                    }
0266:                }
0267:
0268:                try {
0269:                    // Reset the stream for next try.
0270:                    reference.retry();
0271:                } catch (IOException ioe) {
0272:                    reference.release();
0273:                    reference = null;
0274:                    try {
0275:                        // Couldn't reset stream so reopen it.
0276:                        reference = openStream(e, purl);
0277:                    } catch (IOException ioe2) {
0278:                        // Since we already opened the stream this is unlikely.
0279:                        return createBrokenImageNode(ctx, e, purl.toString(),
0280:                                ioe2.getLocalizedMessage());
0281:                    }
0282:                }
0283:
0284:                try {
0285:                    /**
0286:                     * Next see if it's an XML document.
0287:                     */
0288:                    Document doc = loader.loadDocument(purl.toString(),
0289:                            reference);
0290:                    imgDocument = (SVGDocument) doc;
0291:                    return createSVGImageNode(ctx, e, imgDocument);
0292:                } catch (BridgeException ex) {
0293:                    throw ex;
0294:                } catch (SecurityException secEx) {
0295:                    throw new BridgeException(ctx, e, secEx, ERR_URI_UNSECURE,
0296:                            new Object[] { purl });
0297:                } catch (InterruptedIOException iioe) {
0298:                    if (HaltingThread.hasBeenHalted())
0299:                        throw new InterruptedBridgeException();
0300:
0301:                } catch (InterruptedBridgeException ibe) {
0302:                    throw ibe;
0303:                } catch (Exception ex) {
0304:                    /* Nothing to do */
0305:                    // ex.printStackTrace();
0306:                }
0307:
0308:                try {
0309:                    reference.retry();
0310:                } catch (IOException ioe) {
0311:                    reference.release();
0312:                    reference = null;
0313:                    try {
0314:                        // Couldn't reset stream so reopen it.
0315:                        reference = openStream(e, purl);
0316:                    } catch (IOException ioe2) {
0317:                        return createBrokenImageNode(ctx, e, purl.toString(),
0318:                                ioe2.getLocalizedMessage());
0319:                    }
0320:                }
0321:
0322:                try {
0323:                    // Finally try to load the image as a raster image (JPG or
0324:                    // PNG) allowing the registry to open the url (so the
0325:                    // JDK readers can be checked).
0326:                    Filter img = reg.readURL(reference, purl, colorspace, true,
0327:                            true);
0328:                    if (img != null) {
0329:                        // It's a bouncing baby Raster...
0330:                        return createRasterImageNode(ctx, e, img, purl);
0331:                    }
0332:                } finally {
0333:                    reference.release();
0334:                }
0335:                return null;
0336:            }
0337:
0338:            public static class ProtectedStream extends BufferedInputStream {
0339:                static final int BUFFER_SIZE = 8192;
0340:
0341:                ProtectedStream(InputStream is) {
0342:                    super (is, BUFFER_SIZE);
0343:                    super .mark(BUFFER_SIZE); // Remember start
0344:                }
0345:
0346:                ProtectedStream(InputStream is, int size) {
0347:                    super (is, size);
0348:                    super .mark(size); // Remember start
0349:                }
0350:
0351:                public boolean markSupported() {
0352:                    return false;
0353:                }
0354:
0355:                public void mark(int sz) {
0356:                }
0357:
0358:                public void reset() throws IOException {
0359:                    throw new IOException("Reset unsupported");
0360:                }
0361:
0362:                public void retry() throws IOException {
0363:                    super .reset();
0364:                }
0365:
0366:                public void close() throws IOException {
0367:                    /* do nothing */
0368:                }
0369:
0370:                public void release() {
0371:                    try {
0372:                        super .close();
0373:                    } catch (IOException ioe) {
0374:                        // Like Duh! what would you do close it again?
0375:                    }
0376:                }
0377:            }
0378:
0379:            protected ProtectedStream openStream(Element e, ParsedURL purl)
0380:                    throws IOException {
0381:                List mimeTypes = new ArrayList(ImageTagRegistry.getRegistry()
0382:                        .getRegisteredMimeTypes());
0383:                mimeTypes.add(MimeTypeConstants.MIME_TYPES_SVG);
0384:                InputStream reference = purl.openStream(mimeTypes.iterator());
0385:                return new ProtectedStream(reference);
0386:            }
0387:
0388:            /**
0389:             * Creates an <tt>ImageNode</tt>.
0390:             */
0391:            protected GraphicsNode instantiateGraphicsNode() {
0392:                return new ImageNode();
0393:            }
0394:
0395:            /**
0396:             * Returns false as image is not a container.
0397:             */
0398:            public boolean isComposite() {
0399:                return false;
0400:            }
0401:
0402:            // dynamic support
0403:
0404:            /**
0405:             * This method is invoked during the build phase if the document
0406:             * is dynamic. The responsability of this method is to ensure that
0407:             * any dynamic modifications of the element this bridge is
0408:             * dedicated to, happen on its associated GVT product.
0409:             */
0410:            protected void initializeDynamicSupport(BridgeContext ctx,
0411:                    Element e, GraphicsNode node) {
0412:                if (!ctx.isInteractive())
0413:                    return;
0414:
0415:                // Bind the nodes for interactive and dynamic
0416:                // HACK due to the way images are represented in GVT
0417:                ctx.bind(e, node);
0418:
0419:                if (ctx.isDynamic()) {
0420:                    // Only do this for dynamic not interactive.
0421:                    this .e = e;
0422:                    this .node = node;
0423:                    this .ctx = ctx;
0424:                    ((SVGOMElement) e).setSVGContext(this );
0425:                }
0426:            }
0427:
0428:            // BridgeUpdateHandler implementation //////////////////////////////////
0429:
0430:            /**
0431:             * Invoked when the animated value of an animatable attribute has changed.
0432:             */
0433:            public void handleAnimatedAttributeChanged(
0434:                    AnimatedLiveAttributeValue alav) {
0435:                try {
0436:                    String ns = alav.getNamespaceURI();
0437:                    String ln = alav.getLocalName();
0438:                    if (ns == null) {
0439:                        if (ln.equals(SVG_X_ATTRIBUTE)
0440:                                || ln.equals(SVG_Y_ATTRIBUTE)) {
0441:                            updateImageBounds();
0442:                            return;
0443:                        } else if (ln.equals(SVG_WIDTH_ATTRIBUTE)
0444:                                || ln.equals(SVG_HEIGHT_ATTRIBUTE)) {
0445:                            SVGImageElement ie = (SVGImageElement) e;
0446:                            ImageNode imageNode = (ImageNode) node;
0447:                            float val;
0448:                            if (ln.charAt(0) == 'w') {
0449:                                val = ie.getWidth().getAnimVal().getValue();
0450:                            } else {
0451:                                val = ie.getHeight().getAnimVal().getValue();
0452:                            }
0453:                            if (val == 0
0454:                                    || imageNode.getImage() instanceof  ShapeNode) {
0455:                                rebuildImageNode();
0456:                            } else {
0457:                                updateImageBounds();
0458:                            }
0459:                            return;
0460:                        } else if (ln
0461:                                .equals(SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE)) {
0462:                            updateImageBounds();
0463:                            return;
0464:                        }
0465:                    } else if (ns.equals(XLINK_NAMESPACE_URI)
0466:                            && ln.equals(XLINK_HREF_ATTRIBUTE)) {
0467:                        rebuildImageNode();
0468:                        return;
0469:                    }
0470:                } catch (LiveAttributeException ex) {
0471:                    throw new BridgeException(ctx, ex);
0472:                }
0473:                super .handleAnimatedAttributeChanged(alav);
0474:            }
0475:
0476:            protected void updateImageBounds() {
0477:                //retrieve the new bounds of the image tag
0478:                Rectangle2D bounds = getImageBounds(ctx, e);
0479:                GraphicsNode imageNode = ((ImageNode) node).getImage();
0480:                float[] vb = null;
0481:                if (imageNode instanceof  RasterImageNode) {
0482:                    //Raster image
0483:                    Rectangle2D imgBounds = ((RasterImageNode) imageNode)
0484:                            .getImageBounds();
0485:                    // create the implicit viewBox for the raster
0486:                    // image. The viewBox for a raster image is the size
0487:                    // of the image
0488:                    vb = new float[4];
0489:                    vb[0] = 0; // x
0490:                    vb[1] = 0; // y
0491:                    vb[2] = (float) imgBounds.getWidth(); // width
0492:                    vb[3] = (float) imgBounds.getHeight(); // height
0493:                } else {
0494:                    if (imgDocument != null) {
0495:                        Element svgElement = imgDocument.getRootElement();
0496:                        String viewBox = svgElement.getAttributeNS(null,
0497:                                SVG_VIEW_BOX_ATTRIBUTE);
0498:                        vb = ViewBox.parseViewBoxAttribute(e, viewBox, ctx);
0499:                    }
0500:                }
0501:                if (imageNode != null) {
0502:                    // handles the 'preserveAspectRatio', 'overflow' and
0503:                    // 'clip' and sets the appropriate AffineTransform to
0504:                    // the image node
0505:                    initializeViewport(ctx, e, imageNode, vb, bounds);
0506:                }
0507:
0508:            }
0509:
0510:            protected void rebuildImageNode() {
0511:                // Reference copy of the imgDocument
0512:                if ((imgDocument != null) && (listener != null)) {
0513:                    NodeEventTarget tgt = (NodeEventTarget) imgDocument
0514:                            .getRootElement();
0515:
0516:                    tgt.removeEventListenerNS(
0517:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0518:                            SVG_EVENT_CLICK, listener, false);
0519:                    tgt.removeEventListenerNS(
0520:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0521:                            SVG_EVENT_KEYDOWN, listener, false);
0522:                    tgt.removeEventListenerNS(
0523:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0524:                            SVG_EVENT_KEYPRESS, listener, false);
0525:                    tgt.removeEventListenerNS(
0526:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0527:                            SVG_EVENT_KEYUP, listener, false);
0528:                    tgt.removeEventListenerNS(
0529:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0530:                            SVG_EVENT_MOUSEDOWN, listener, false);
0531:                    tgt.removeEventListenerNS(
0532:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0533:                            SVG_EVENT_MOUSEMOVE, listener, false);
0534:                    tgt.removeEventListenerNS(
0535:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0536:                            SVG_EVENT_MOUSEOUT, listener, false);
0537:                    tgt.removeEventListenerNS(
0538:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0539:                            SVG_EVENT_MOUSEOVER, listener, false);
0540:                    tgt.removeEventListenerNS(
0541:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0542:                            SVG_EVENT_MOUSEUP, listener, false);
0543:                    listener = null;
0544:                }
0545:
0546:                if (imgDocument != null) {
0547:                    SVGSVGElement svgElement = imgDocument.getRootElement();
0548:                    disposeTree(svgElement);
0549:                }
0550:
0551:                imgDocument = null;
0552:                subCtx = null;
0553:
0554:                //update of the reference of the image.
0555:                GraphicsNode inode = buildImageGraphicsNode(ctx, e);
0556:
0557:                ImageNode imgNode = (ImageNode) node;
0558:                imgNode.setImage(inode);
0559:
0560:                if (inode == null) {
0561:                    SVGImageElement ie = (SVGImageElement) e;
0562:                    String uriStr = ie.getHref().getAnimVal();
0563:                    throw new BridgeException(ctx, e, ERR_URI_IMAGE_INVALID,
0564:                            new Object[] { uriStr });
0565:                }
0566:            }
0567:
0568:            /**
0569:             * Invoked for each CSS property that has changed.
0570:             */
0571:            protected void handleCSSPropertyChanged(int property) {
0572:                switch (property) {
0573:                case SVGCSSEngine.IMAGE_RENDERING_INDEX:
0574:                case SVGCSSEngine.COLOR_INTERPOLATION_INDEX:
0575:                    RenderingHints hints = CSSUtilities.convertImageRendering(
0576:                            e, null);
0577:                    hints = CSSUtilities.convertColorRendering(e, hints);
0578:                    if (hints != null) {
0579:                        node.setRenderingHints(hints);
0580:                    }
0581:                    break;
0582:                default:
0583:                    super .handleCSSPropertyChanged(property);
0584:                }
0585:            }
0586:
0587:            // convenient methods //////////////////////////////////////////////////
0588:
0589:            /**
0590:             * Returns a GraphicsNode that represents an raster image in JPEG or PNG
0591:             * format.
0592:             *
0593:             * @param ctx the bridge context
0594:             * @param e the image element
0595:             * @param img the image to use in creating the graphics node
0596:             */
0597:            protected GraphicsNode createRasterImageNode(BridgeContext ctx,
0598:                    Element e, Filter img, ParsedURL purl) {
0599:                Rectangle2D bounds = getImageBounds(ctx, e);
0600:                if ((bounds.getWidth() == 0) || (bounds.getHeight() == 0)) {
0601:                    ShapeNode sn = new ShapeNode();
0602:                    sn.setShape(bounds);
0603:                    return sn;
0604:                }
0605:
0606:                if (BrokenLinkProvider.hasBrokenLinkProperty(img)) {
0607:                    Object o = img
0608:                            .getProperty(BrokenLinkProvider.BROKEN_LINK_PROPERTY);
0609:                    String msg = "unknown";
0610:                    if (o instanceof  String)
0611:                        msg = (String) o;
0612:                    SVGDocument doc = ctx.getUserAgent().getBrokenLinkDocument(
0613:                            e, purl.toString(), msg);
0614:                    return createSVGImageNode(ctx, e, doc);
0615:                }
0616:
0617:                RasterImageNode node = new RasterImageNode();
0618:                node.setImage(img);
0619:                Rectangle2D imgBounds = img.getBounds2D();
0620:
0621:                // create the implicit viewBox for the raster image. The viewBox for a
0622:                // raster image is the size of the image
0623:                float[] vb = new float[4];
0624:                vb[0] = 0; // x
0625:                vb[1] = 0; // y
0626:                vb[2] = (float) imgBounds.getWidth(); // width
0627:                vb[3] = (float) imgBounds.getHeight(); // height
0628:
0629:                // handles the 'preserveAspectRatio', 'overflow' and 'clip' and sets the
0630:                // appropriate AffineTransform to the image node
0631:                initializeViewport(ctx, e, node, vb, bounds);
0632:
0633:                return node;
0634:            }
0635:
0636:            /**
0637:             * Returns a GraphicsNode that represents a svg document as an image.
0638:             *
0639:             * @param ctx the bridge context
0640:             * @param e the image element
0641:             * @param imgDocument the SVG document that represents the image
0642:             */
0643:            protected GraphicsNode createSVGImageNode(BridgeContext ctx,
0644:                    Element e, SVGDocument imgDocument) {
0645:                CSSEngine eng = ((SVGOMDocument) imgDocument).getCSSEngine();
0646:                subCtx = ctx
0647:                        .createSubBridgeContext((SVGOMDocument) imgDocument);
0648:
0649:                CompositeGraphicsNode result = new CompositeGraphicsNode();
0650:                // handles the 'preserveAspectRatio', 'overflow' and 'clip' and
0651:                // sets the appropriate AffineTransform to the image node
0652:                Rectangle2D bounds = getImageBounds(ctx, e);
0653:
0654:                if ((bounds.getWidth() == 0) || (bounds.getHeight() == 0)) {
0655:                    ShapeNode sn = new ShapeNode();
0656:                    sn.setShape(bounds);
0657:                    result.getChildren().add(sn);
0658:                    return result;
0659:                }
0660:
0661:                Rectangle2D r = CSSUtilities.convertEnableBackground(e);
0662:                if (r != null) {
0663:                    result.setBackgroundEnable(r);
0664:                }
0665:
0666:                SVGSVGElement svgElement = imgDocument.getRootElement();
0667:                CanvasGraphicsNode node;
0668:                node = (CanvasGraphicsNode) subCtx.getGVTBuilder().build(
0669:                        subCtx, svgElement);
0670:
0671:                if ((eng == null) && ctx.isInteractive()) {
0672:                    // If we "created" this document then add listerns.
0673:                    subCtx.addUIEventListeners(imgDocument);
0674:                }
0675:
0676:                // HACK: remove the clip set by the SVGSVGElement as the overflow
0677:                // and clip properties must be ignored. The clip will be set later
0678:                // using the overflow and clip of the <image> element.
0679:                node.setClip(null);
0680:                // HACK: remove the viewingTransform set by the SVGSVGElement
0681:                // as the viewBox must be ignored. The viewingTransform will
0682:                // be set later using the width/height of the image element.
0683:                node.setViewingTransform(new AffineTransform());
0684:                result.getChildren().add(node);
0685:
0686:                // create the implicit viewBox for the SVG image. The viewBox for a
0687:                // SVG image is the viewBox of the outermost SVG element of the SVG file
0688:                String viewBox = svgElement.getAttributeNS(null,
0689:                        SVG_VIEW_BOX_ATTRIBUTE);
0690:                float[] vb = ViewBox.parseViewBoxAttribute(e, viewBox, ctx);
0691:
0692:                initializeViewport(ctx, e, result, vb, bounds);
0693:
0694:                // add a listener on the outermost svg element of the SVG image.
0695:                // if an event occured inside the SVG image document, send it
0696:                // to the <image> element (inside the original document).
0697:                if (ctx.isInteractive()) {
0698:                    listener = new ForwardEventListener(svgElement, e);
0699:                    NodeEventTarget tgt = (NodeEventTarget) svgElement;
0700:
0701:                    tgt.addEventListenerNS(
0702:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0703:                            SVG_EVENT_CLICK, listener, false, null);
0704:                    subCtx.storeEventListenerNS(tgt,
0705:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0706:                            SVG_EVENT_CLICK, listener, false);
0707:
0708:                    tgt.addEventListenerNS(
0709:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0710:                            SVG_EVENT_KEYDOWN, listener, false, null);
0711:                    subCtx.storeEventListenerNS(tgt,
0712:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0713:                            SVG_EVENT_KEYDOWN, listener, false);
0714:
0715:                    tgt.addEventListenerNS(
0716:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0717:                            SVG_EVENT_KEYPRESS, listener, false, null);
0718:                    subCtx.storeEventListenerNS(tgt,
0719:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0720:                            SVG_EVENT_KEYPRESS, listener, false);
0721:
0722:                    tgt.addEventListenerNS(
0723:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0724:                            SVG_EVENT_KEYUP, listener, false, null);
0725:                    subCtx.storeEventListenerNS(tgt,
0726:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0727:                            SVG_EVENT_KEYUP, listener, false);
0728:
0729:                    tgt.addEventListenerNS(
0730:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0731:                            SVG_EVENT_MOUSEDOWN, listener, false, null);
0732:                    subCtx.storeEventListenerNS(tgt,
0733:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0734:                            SVG_EVENT_MOUSEDOWN, listener, false);
0735:
0736:                    tgt.addEventListenerNS(
0737:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0738:                            SVG_EVENT_MOUSEMOVE, listener, false, null);
0739:                    subCtx.storeEventListenerNS(tgt,
0740:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0741:                            SVG_EVENT_MOUSEMOVE, listener, false);
0742:
0743:                    tgt.addEventListenerNS(
0744:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0745:                            SVG_EVENT_MOUSEOUT, listener, false, null);
0746:                    subCtx.storeEventListenerNS(tgt,
0747:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0748:                            SVG_EVENT_MOUSEOUT, listener, false);
0749:
0750:                    tgt.addEventListenerNS(
0751:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0752:                            SVG_EVENT_MOUSEOVER, listener, false, null);
0753:                    subCtx.storeEventListenerNS(tgt,
0754:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0755:                            SVG_EVENT_MOUSEOVER, listener, false);
0756:
0757:                    tgt.addEventListenerNS(
0758:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0759:                            SVG_EVENT_MOUSEUP, listener, false, null);
0760:                    subCtx.storeEventListenerNS(tgt,
0761:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0762:                            SVG_EVENT_MOUSEUP, listener, false);
0763:                }
0764:
0765:                return result;
0766:            }
0767:
0768:            public void dispose() {
0769:                if ((imgDocument != null) && (listener != null)) {
0770:                    NodeEventTarget tgt = (NodeEventTarget) imgDocument
0771:                            .getRootElement();
0772:
0773:                    tgt.removeEventListenerNS(
0774:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0775:                            SVG_EVENT_CLICK, listener, false);
0776:                    tgt.removeEventListenerNS(
0777:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0778:                            SVG_EVENT_KEYDOWN, listener, false);
0779:                    tgt.removeEventListenerNS(
0780:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0781:                            SVG_EVENT_KEYPRESS, listener, false);
0782:                    tgt.removeEventListenerNS(
0783:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0784:                            SVG_EVENT_KEYUP, listener, false);
0785:                    tgt.removeEventListenerNS(
0786:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0787:                            SVG_EVENT_MOUSEDOWN, listener, false);
0788:                    tgt.removeEventListenerNS(
0789:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0790:                            SVG_EVENT_MOUSEMOVE, listener, false);
0791:                    tgt.removeEventListenerNS(
0792:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0793:                            SVG_EVENT_MOUSEOUT, listener, false);
0794:                    tgt.removeEventListenerNS(
0795:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0796:                            SVG_EVENT_MOUSEOVER, listener, false);
0797:                    tgt.removeEventListenerNS(
0798:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0799:                            SVG_EVENT_MOUSEUP, listener, false);
0800:                    listener = null;
0801:                }
0802:
0803:                if (imgDocument != null) {
0804:                    SVGSVGElement svgElement = imgDocument.getRootElement();
0805:                    disposeTree(svgElement);
0806:                    imgDocument = null;
0807:                    subCtx = null;
0808:                }
0809:                super .dispose();
0810:
0811:            }
0812:
0813:            /**
0814:             * A simple DOM listener to forward events from the SVG image document to
0815:             * the original document.
0816:             */
0817:            protected static class ForwardEventListener implements 
0818:                    EventListener {
0819:
0820:                /**
0821:                 * The root element of the SVG image.
0822:                 */
0823:                protected Element svgElement;
0824:
0825:                /**
0826:                 * The image element.
0827:                 */
0828:                protected Element imgElement;
0829:
0830:                /**
0831:                 * Constructs a new <tt>ForwardEventListener</tt>
0832:                 */
0833:                public ForwardEventListener(Element svgElement,
0834:                        Element imgElement) {
0835:                    this .svgElement = svgElement;
0836:                    this .imgElement = imgElement;
0837:                }
0838:
0839:                public void handleEvent(Event e) {
0840:                    DOMMouseEvent evt = (DOMMouseEvent) e;
0841:                    DOMMouseEvent newMouseEvent = (DOMMouseEvent)
0842:                    // DOM Level 2 6.5 cast from Document to DocumentEvent is ok
0843:                    ((DocumentEvent) imgElement.getOwnerDocument())
0844:                            .createEvent("MouseEvents");
0845:
0846:                    newMouseEvent.initMouseEventNS(
0847:                            XMLConstants.XML_EVENTS_NAMESPACE_URI, evt
0848:                                    .getType(), evt.getBubbles(), evt
0849:                                    .getCancelable(), evt.getView(), evt
0850:                                    .getDetail(), evt.getScreenX(), evt
0851:                                    .getScreenY(), evt.getClientX(), evt
0852:                                    .getClientY(), evt.getButton(),
0853:                            (EventTarget) imgElement, evt.getModifiersString());
0854:                    ((EventTarget) imgElement).dispatchEvent(newMouseEvent);
0855:                }
0856:            }
0857:
0858:            /**
0859:             * Initializes according to the specified element, the specified graphics
0860:             * node with the specified bounds. This method takes into account the
0861:             * 'viewBox', 'preserveAspectRatio', and 'clip' properties. According to
0862:             * those properties, a AffineTransform and a clip is set.
0863:             *
0864:             * @param ctx the bridge context
0865:             * @param e the image element that defines the properties
0866:             * @param node the graphics node
0867:             * @param vb the implicit viewBox definition
0868:             * @param bounds the bounds of the image element
0869:             */
0870:            protected static void initializeViewport(BridgeContext ctx,
0871:                    Element e, GraphicsNode node, float[] vb, Rectangle2D bounds) {
0872:
0873:                float x = (float) bounds.getX();
0874:                float y = (float) bounds.getY();
0875:                float w = (float) bounds.getWidth();
0876:                float h = (float) bounds.getHeight();
0877:
0878:                try {
0879:                    SVGImageElement ie = (SVGImageElement) e;
0880:                    SVGAnimatedPreserveAspectRatio aPAR = ie
0881:                            .getPreserveAspectRatio();
0882:
0883:                    AffineTransform at = ViewBox
0884:                            .getPreserveAspectRatioTransform(e, vb, w, h, aPAR,
0885:                                    ctx);
0886:                    at.preConcatenate(AffineTransform
0887:                            .getTranslateInstance(x, y));
0888:                    node.setTransform(at);
0889:
0890:                    // 'overflow' and 'clip'
0891:                    Shape clip = null;
0892:                    if (CSSUtilities.convertOverflow(e)) { // overflow:hidden
0893:                        float[] offsets = CSSUtilities.convertClip(e);
0894:                        if (offsets == null) { // clip:auto
0895:                            clip = new Rectangle2D.Float(x, y, w, h);
0896:                        } else { // clip:rect(<x> <y> <w> <h>)
0897:                            // offsets[0] = top
0898:                            // offsets[1] = right
0899:                            // offsets[2] = bottom
0900:                            // offsets[3] = left
0901:                            clip = new Rectangle2D.Float(x + offsets[3], y
0902:                                    + offsets[0], w - offsets[1] - offsets[3],
0903:                                    h - offsets[2] - offsets[0]);
0904:                        }
0905:                    }
0906:
0907:                    if (clip != null) {
0908:                        try {
0909:                            at = at.createInverse(); // clip in user space
0910:                            Filter filter = node.getGraphicsNodeRable(true);
0911:                            clip = at.createTransformedShape(clip);
0912:                            node.setClip(new ClipRable8Bit(filter, clip));
0913:                        } catch (java.awt.geom.NoninvertibleTransformException ex) {
0914:                        }
0915:                    }
0916:                } catch (LiveAttributeException ex) {
0917:                    throw new BridgeException(ctx, ex);
0918:                }
0919:            }
0920:
0921:            /**
0922:             * Analyzes the color-profile property and builds an ICCColorSpaceExt
0923:             * object from it.
0924:             *
0925:             * @param element the element with the color-profile property
0926:             * @param ctx the bridge context
0927:             */
0928:            protected static ICCColorSpaceExt extractColorSpace(
0929:                    Element element, BridgeContext ctx) {
0930:
0931:                String colorProfileProperty = CSSUtilities.getComputedStyle(
0932:                        element, SVGCSSEngine.COLOR_PROFILE_INDEX)
0933:                        .getStringValue();
0934:
0935:                // The only cases that need special handling are 'sRGB' and 'name'
0936:                ICCColorSpaceExt colorSpace = null;
0937:                if (CSS_SRGB_VALUE.equalsIgnoreCase(colorProfileProperty)) {
0938:
0939:                    colorSpace = new ICCColorSpaceExt(ICC_Profile
0940:                            .getInstance(ColorSpace.CS_sRGB),
0941:                            ICCColorSpaceExt.AUTO);
0942:
0943:                } else if (!CSS_AUTO_VALUE
0944:                        .equalsIgnoreCase(colorProfileProperty)
0945:                        && !"".equalsIgnoreCase(colorProfileProperty)) {
0946:
0947:                    // The value is neither 'sRGB' nor 'auto': it is a profile name.
0948:                    SVGColorProfileElementBridge profileBridge = (SVGColorProfileElementBridge) ctx
0949:                            .getBridge(SVG_NAMESPACE_URI, SVG_COLOR_PROFILE_TAG);
0950:                    if (profileBridge != null) {
0951:                        colorSpace = profileBridge.createICCColorSpaceExt(ctx,
0952:                                element, colorProfileProperty);
0953:
0954:                    }
0955:                }
0956:                return colorSpace;
0957:            }
0958:
0959:            /**
0960:             * Returns the bounds of the specified image element.
0961:             *
0962:             * @param ctx the bridge context
0963:             * @param element the image element
0964:             */
0965:            protected static Rectangle2D getImageBounds(BridgeContext ctx,
0966:                    Element element) {
0967:                try {
0968:                    SVGImageElement ie = (SVGImageElement) element;
0969:
0970:                    // 'x' attribute - default is 0
0971:                    float x = ie.getX().getAnimVal().getValue();
0972:
0973:                    // 'y' attribute - default is 0
0974:                    float y = ie.getY().getAnimVal().getValue();
0975:
0976:                    // 'width' attribute - required
0977:                    float w = ie.getWidth().getAnimVal().getValue();
0978:
0979:                    // 'height' attribute - required
0980:                    float h = ie.getHeight().getAnimVal().getValue();
0981:
0982:                    return new Rectangle2D.Float(x, y, w, h);
0983:                } catch (LiveAttributeException ex) {
0984:                    throw new BridgeException(ctx, ex);
0985:                }
0986:            }
0987:
0988:            GraphicsNode createBrokenImageNode(BridgeContext ctx, Element e,
0989:                    String uri, String message) {
0990:                SVGDocument doc = ctx.getUserAgent().getBrokenLinkDocument(
0991:                        e,
0992:                        uri,
0993:                        Messages.formatMessage(URI_IMAGE_ERROR,
0994:                                new Object[] { message }));
0995:                return createSVGImageNode(ctx, e, doc);
0996:            }
0997:
0998:            static SVGBrokenLinkProvider brokenLinkProvider = new SVGBrokenLinkProvider();
0999:            static {
1000:                ImageTagRegistry.setBrokenLinkProvider(brokenLinkProvider);
1001:            }
1002:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.