FileDocCategorySizeDatePackage
SVGImageImpl.javaAPI DocphoneME MR2 API (J2ME)16620Wed May 02 18:00:36 BST 2007com.sun.perseus.model

SVGImageImpl

public class SVGImageImpl extends javax.microedition.m2g.SVGImage

Fields Summary
static final int
DEFAULT_IMAGE_READ_BUFFER_LENGTH
Size of the byte buffer used to read image input streams handed by ExternalResourceHandler implementations.
com.sun.perseus.model.DocumentNode
documentNode
The image document
public static final int
DEFAULT_WIDTH
The default width for an empty SVG image
public static final int
DEFAULT_HEIGHT
The default height for an empty SVG image
SVGImageLoader
svgImageLoader
The SVGImageLoader
org.w3c.dom.svg.SVGElement
lastElement
The current SVGElement with the focus
String
waitURI
URI requested by SVGImageLoader's getImageAndWait().
boolean
isBrokenImage
Received null resourceData in requestCompleted(). Used in getImageAndWait() case.
Constructors Summary
private SVGImageImpl(com.sun.perseus.model.DocumentNode documentNode, javax.microedition.m2g.ExternalResourceHandler handler)
Private constructor. Requires a non null DocumentNode.

param
documentNode the associated DocumentNode. Should not be null.
param
ExternalResourceHandler the associated handler.

        this.documentNode = documentNode;

        if (handler != null) {
            svgImageLoader = new SVGImageLoader(this, handler);
            documentNode.setImageLoader(svgImageLoader);
        } else {
            documentNode.setImageLoader(new DefaultImageLoader());
        }
    
Methods Summary
public voidactivate()

        if (lastElement == null) {
            return;
        }

        documentNode.dispatchEvent(documentNode.initEngineEvent(
                SVGConstants.SVG_DOMACTIVATE_EVENT_TYPE, 
                (ModelNode) lastElement));
    
public static javax.microedition.m2g.SVGImagecreateEmptyImage(javax.microedition.m2g.ExternalResourceHandler handler)

        DocumentNode documentNode = new DocumentNode();

        SVG svg = new SVG(documentNode);
        svg.setWidth((float) DEFAULT_WIDTH);
        svg.setHeight((float) DEFAULT_HEIGHT);
        documentNode.add(svg);

        documentNode.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);

        SVGImageImpl sii = new SVGImageImpl(documentNode, handler);

        // Add prototypes for the SVG Tiny elements.
        Vector prototypes = SVGTinyModelFactory.getPrototypes(documentNode);
        int n = prototypes.size();
        for (int i = 0; i < n; i++) {
            documentNode.addPrototype((ElementNode) prototypes.elementAt(i));
        }

        // Initialize the timing engine and sample at time zero.
        documentNode.initializeTimingEngine();
        documentNode.sample(new Time(0));
        documentNode.setLoaded(true);

        return sii;
    
public static javax.microedition.m2g.ScalableImagecreateImage(java.lang.String URL, javax.microedition.m2g.ExternalResourceHandler handler)

        if (URL == null) {
            throw new NullPointerException();
        }

        DocumentNode documentNode = new DocumentNode();
        documentNode.setDocumentURI(URL);

        InputStream is = null;

        try {
            is = GZIPSupport.openHandleGZIP(URL);
        } catch (IOException ioe) {
            throw new IllegalArgumentException(ioe.getMessage());
        }

        return loadDocument(documentNode, is, handler);
    
public static javax.microedition.m2g.ScalableImagecreateImage(java.io.InputStream stream, javax.microedition.m2g.ExternalResourceHandler handler)

        if (stream == null) {
            throw new NullPointerException();
        }

        DocumentNode documentNode = new DocumentNode();

        return loadDocument(documentNode, stream, handler);
    
public voiddispatchMouseEvent(java.lang.String type, int x, int y)
This method is used to dispatch a mouse event of the specified type to the document. The mouse position is given as screen coordinates x, y. The only mouse event type supported is "click". Note that when a "click" event is dispatched, a "DOMActivate" is automatically dispatched by the underlying implementation. If a different type is specified, a DOMException with error code NOT_SUPPORTED_ERR is thrown. In the case, where x, y values are outside the viewport area or no target is available for the x, y coordinates, the event is not dispatched.

param
type the type of mouse event.
param
x the x location of the mouse/pointer in viewport coordinate system.
param
y the y location of the mouse/pointer in viewport coordinate system.
throws
DOMException with error code NOT_SUPPORTED_ERR: if the event type is not supported.
throws
NullPointerException if type is null.
throws
IllegalArgumentException if the x or y values are negative.


        if (type == null) {
            throw new NullPointerException();
        }

        if (x < 0 || y < 0) {
            throw new IllegalArgumentException();
        }

        if (!type.equals(SVGConstants.SVG_CLICK_EVENT_TYPE)) {
            throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 
                                   "Event type is NOT click.");
        }

        // CHECK x,y outside the viewport area
        if (x > getViewportWidth() || y > getViewportHeight()) {
            return;
        }

        // Get the target hit by the mouse event
        float[] pt = {x, y};
        ModelNode target = documentNode.nodeHitAt(pt);

        if (target == null) {
            return;
        }

        // Dispatch an activate on the element that was clicked on.
        documentNode.dispatchEvent(documentNode.initEngineEvent(
                SVGConstants.SVG_DOMACTIVATE_EVENT_TYPE, 
                target));


        // Now, dispatch the click event.
        documentNode.dispatchEvent
            (documentNode.initEngineEvent(SVGConstants.SVG_CLICK_EVENT_TYPE, 
                                          target));
    
public voidfocusOn(org.w3c.dom.svg.SVGElement element)

        if (element == null) {
            if (lastElement != null) {
                // remove current focus
                documentNode.dispatchEvent(documentNode.initEngineEvent(
                        SVGConstants.SVG_DOMFOCUSOUT_EVENT_TYPE, 
                        (ModelNode) lastElement));
                lastElement = null;
            }
            return;
        }

        DocumentNode ownerDocument = ((ModelNode) element).getOwnerDocument();
        if (!ownerDocument.equals(documentNode)) {
            throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, 
                                   "Invalid element.");
        }

        // If this element is different from the previous element focused,
        // dispatch a "DOMFocusOut" event to the previous element.
        if (lastElement != element) {
            if (lastElement != null) {
                documentNode.dispatchEvent(documentNode.initEngineEvent(
                        SVGConstants.SVG_DOMFOCUSOUT_EVENT_TYPE, 
                        (ModelNode) lastElement));
            }

            documentNode.dispatchEvent(documentNode.initEngineEvent(
                    SVGConstants.SVG_DOMFOCUSIN_EVENT_TYPE, 
                    (ModelNode) element));

            lastElement = element;
        }
    
public org.w3c.dom.DocumentgetDocument()
Returns the associated Document.

return
the associated Document.


                 
       
        return (Document) documentNode;
    
public intgetViewportHeight()

        return documentNode.getHeight();
    
public intgetViewportWidth()

        return documentNode.getWidth();
    
public voidincrementTime(float seconds)

        if (documentNode.updateQueue == null) {
            // We are not running with an update queue, which means we are 
            // not running withing an SVGAnimator. Therefore, we simply
            // increment time.
            documentNode.incrementTime(seconds);
        } else {
            // The impact of changing the time must be made visible immediately
            // because the document is being displayed in an
            // SVGAnimator. Therefore, we force the document to sample and apply
            // animations so that resulting rendering changes get displayed
            // immediately.

            // We are running in an update queue. Check whether or not we are
            // already in the update thread.
            if (Thread.currentThread() 
                == documentNode.updateQueue.getThread()) {
                // We are already in the right thread. 
                documentNode.incrementTime(seconds);
                documentNode.applyAnimations();
            } else {
                // We are in the wrong thread. Move to the right thread.
                documentNode.safeInvokeAndWait(new Runnable() {
                        public void run() {
                            documentNode.incrementTime(seconds);
                            documentNode.applyAnimations();
                        }
                    });
            }
        }
    
private static javax.microedition.m2g.ScalableImageloadDocument(com.sun.perseus.model.DocumentNode documentNode, java.io.InputStream is, javax.microedition.m2g.ExternalResourceHandler handler)
Implementation helper.

param
documentNode the DocumentNode object into which the content of the stream should be loaded.
param
is the InputStream to the content to be loaded.
param
handler the ExternalResourceHandler. May be null.

        UpdateAdapter updateAdapter = new UpdateAdapter();
        documentNode.setUpdateListener(updateAdapter);

        SVGImageImpl sii = new SVGImageImpl(documentNode, handler);

        ModelBuilder.loadDocument(is, documentNode);

        if (updateAdapter.hasLoadingFailed()) {
            if (updateAdapter.getLoadingFailedException() != null) {
                throw new IOException
                    (updateAdapter.getLoadingFailedException().getMessage());
            }
            throw new IOException();
        }

        // Now, get image width/height from <svg> element and set it in
        // DocumentNode
        Element root = documentNode.getDocumentElement();
        if (!(root instanceof SVG)) {
            throw new IOException(Messages.formatMessage(
                    Messages.ERROR_NON_SVG_RESOURCE,
                    new String[] {documentNode.getURIBase()}));
        }

        SVG svg = (SVG) root;
        int width = (int) svg.getWidth();
        int height = (int) svg.getHeight();
        documentNode.setSize(width, height);

        // Now, initialize the timing engine and sample at zero.
        documentNode.initializeTimingEngine();
        documentNode.sample(new Time(0));
        return sii;        
    
public voidrequestCompleted(java.lang.String uri, java.io.InputStream resourceData)

        System.err.println(">>>>> requestCompleted : " + uri + " / " 
                            + resourceData);
        if (uri == null) {
            throw new NullPointerException();
        }

        synchronized (this) {
            // set in getImageAndWait()
            boolean isWaitURI = waitURI.equals(uri);

            RasterImage img;

            // null resourceData...
            if (resourceData == null) {
                img = svgImageLoader.getBrokenImage();
                isBrokenImage = true;
            } else {
                // we got a fresh, new image...
                ByteArrayOutputStream bos = new ByteArrayOutputStream(
                        DEFAULT_IMAGE_READ_BUFFER_LENGTH);
                byte[] ib = new byte[DEFAULT_IMAGE_READ_BUFFER_LENGTH];
                int byteRead = -1;
                int totalByteRead = 0;
                while ((byteRead = resourceData.read(ib, 0, ib.length)) != -1) {
                    bos.write(ib, 0, byteRead);
                    totalByteRead += byteRead;
                }
                
                img = svgImageLoader.loaderUtil.createImage(bos.toByteArray());
            }

            // the new image is added to cache...
            svgImageLoader.addToCache(uri, img);

            svgImageLoader.setRasterImageConsumerImage(uri, img);
            
            // request was initiated by getImageAndWait
            if (isWaitURI) {
                notifyAll();
            }
        }
    
public voidsetViewportHeight(int height)

        if (height < 0) {
            throw new IllegalArgumentException();
        }

        documentNode.setSize(documentNode.getWidth(), height);
    
public voidsetViewportWidth(int width)
An area where the ScalableImage is rendered is called viewport. If a part of the viewport lays outside of the target clipping rectangle it is clipped. The viewport coordinates are given relative to the target rendering surface.

        if (width < 0) {
            throw new IllegalArgumentException();
        }

        documentNode.setSize(width, documentNode.getHeight());
    
synchronized com.sun.perseus.j2d.RasterImagewaitOnRequestCompleted(java.lang.String uri)

        waitURI = uri;

        try {
            while (isBrokenImage == false &&
                   svgImageLoader.getImageFromCache(uri) == null) {
                wait();
            }
        } catch (InterruptedException ie) {
            return svgImageLoader.getBrokenImage();
        }

        waitURI = new String();
        if (isBrokenImage) {
            isBrokenImage = false;
            return svgImageLoader.getBrokenImage();
        } else {
            return svgImageLoader.getImageFromCache(uri);
        }