javauis/m2g_qt/javasrc/com/nokia/microedition/m2g/M2GSVGImage.java
author hgs
Fri, 29 Oct 2010 11:49:32 +0300
changeset 87 1627c337e51e
parent 80 d6dafc5d983f
permissions -rw-r--r--
v2.2.21_1

/*
* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/

package com.nokia.microedition.m2g;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.microedition.m2g.ExternalResourceHandler;
import javax.microedition.m2g.SVGImage;
import org.w3c.dom.Document;
import org.w3c.dom.svg.SVGElement;
import org.w3c.dom.DOMException;
import com.nokia.microedition.m2g.connection.*;
import com.nokia.mj.impl.utils.Logger;
import com.nokia.mj.impl.utils.StreamUtils;


/*
 * Image implementation
 */
public class M2GSVGImage
        extends SVGImage
{
    //--------------------------------------------------
    // STATIC CONSTANTS
    //--------------------------------------------------


    //--------------------------------------------------
    //  VARIABLES
    //--------------------------------------------------
    M2GDocument iDocument = null;
    private SVGElement iFocusedNode = null;

    //--------------------------------------------------
    //  METHODS
    //--------------------------------------------------
    /**
     * Constructor
     */
    M2GSVGImage()
    {
        super();
    }

    /**
     * @see javax.microedition.m2g.SVGImage#activate()
     */
    public void activate()
    {
        SVGElement node = iFocusedNode;
        while (node != null)
        {
            ((M2GDocument)getDocument()).handleEvent(new M2GEvent(
                        M2GSVGConstants.EVENT_ACTIVATE,
                        node,
                        M2GEvent.EVENT_TARGET));
            node = (SVGElement)node.getParentNode();
        }
    }

    /**
     * @see javax.microedition.m2g.SVGImage#dispatchMouseEvent()
     */
    public void dispatchMouseEvent(String type, int x, int y)
    {
        if (type == null || type.equals(""))
        {
            Logger.ELOG(Logger.EJavaUI, "dispatchMouseEvent() NullPointerException");
            throw new NullPointerException(/*SF*/"The type is null."/*SF*/);
        }
        if (x < 0 || y < 0)
        {
            Logger.ELOG(Logger.EJavaUI,
                        "dispatchMouseEvent() IllegalArgumentException");
            throw new IllegalArgumentException(/*SF*/"The x or y values are negative."/*SF*/);
        }
        if (!type.equals(M2GSVGConstants.EVENT_CLICK))
        {
            Logger.ELOG(Logger.EJavaUI,
                        "dispatchMouseEvent() DOMException - only click event is supported");
            throw new DOMException(DOMException.NOT_SUPPORTED_ERR, /*SF*/"The event type is not supported."/*SF*/);
        }
        int elementHandle = _dispatchMouseEvent(
                                iDocument.getNativeSVGProxyHandle(),
                                iDocument.getHandle(), x, y);

        SVGElement targetElement = M2GSVGElement.buildElement(elementHandle, iDocument);
        SVGElement usedFromElement = null;
        if ((targetElement != null) && ((M2GSVGElement)targetElement).isUsed())
        {
            usedFromElement = ((M2GSVGElement)((M2GSVGElement)targetElement).getUsedFromElement());
        }
        if (targetElement instanceof M2GSVGElement)
        {
            iFocusedNode = targetElement;
        }
        while (targetElement != null)
        {
            // click event
            iDocument.handleEvent(new M2GEvent(
                                      M2GSVGConstants.EVENT_CLICK, targetElement, M2GEvent.EVENT_TARGET));
            // DOMActivate event
            iDocument.handleEvent(new M2GEvent(
                                      M2GSVGConstants.EVENT_ACTIVATE, targetElement, M2GEvent.EVENT_TARGET));
            // Gets parent node
            targetElement = (SVGElement)targetElement.getParentNode();
        }
        // The "target element" is only a clone. The "used from element" is the actual element.
        if (usedFromElement != null)
        {
            iDocument.handleEvent(new M2GEvent(
                                      M2GSVGConstants.EVENT_CLICK, usedFromElement, M2GEvent.WRAPPED_EVENT_TARGET));
            iDocument.handleEvent(new M2GEvent(
                                      M2GSVGConstants.EVENT_ACTIVATE, usedFromElement, M2GEvent.WRAPPED_EVENT_TARGET));
        }
    }

    /**
     * @see javax.microedition.m2g.SVGImage#focusOn()
     */
    public void focusOn(SVGElement element)
    {
        SVGElement tempNode = element;
        // If focusOn is called on the same element, do not focus out.
        boolean callFocusOut =
            (((iFocusedNode != null) && (iFocusedNode == element ? false : true)) || ((iFocusedNode != null) && (element == null)));
        //Checking to see if the element is hooked into the tree.
        if (element != null)
        {
            tempNode = element;
            while (tempNode != null)
            {
                if ((tempNode.getLocalName()).equals(M2GSVGConstants.ROOT_SVG_ELEMENT_NAME))
                {
                    // Breaks if tempNode is root svg
                    break;
                }
                tempNode = (SVGElement)tempNode.getParentNode();
            }
            // This indicates that the element does not contain a root element,
            // therefore does not belong to the document.
            if (tempNode == null)
            {
                Logger.ELOG(Logger.EJavaUI, "focusOn() - DOMException invalid element");
                throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, /*SF*/"Invalid element."/*SF*/);
            }
        }
        // Focus out from the current focused node and its parents
        if (callFocusOut)
        {
            if (iFocusedNode instanceof M2GSVGElement)
            {
                _focusOut(
                    ((M2GSVGElement)iFocusedNode).getNativeSVGProxyHandle(),
                    ((M2GSVGElement)iFocusedNode).getDocument().getHandle(),
                    ((M2GSVGElement)iFocusedNode).getHandle());
            }

            // Focus out the current focused node and its parents
            tempNode = iFocusedNode;
            while (tempNode != null)
            {
                iDocument.handleEvent(new M2GEvent(
                                          M2GSVGConstants.EVENT_FOCUS_OUT, tempNode, M2GEvent.EVENT_TARGET));
                tempNode = (SVGElement)tempNode.getParentNode();
            }
        }
        //focus in for element and its parents
        if ((element != null) && (element instanceof M2GSVGElement))
        {
            _focusOn(
                ((M2GSVGElement)element).getNativeSVGProxyHandle(),
                ((M2GSVGElement)element).getDocument().getHandle(),
                ((M2GSVGElement)element).getHandle());
        }
        tempNode = element;
        while (tempNode != null)
        {
            iDocument.handleEvent(new M2GEvent(
                                      M2GSVGConstants.EVENT_FOCUS_IN, tempNode, M2GEvent.EVENT_TARGET));
            tempNode = (SVGElement)tempNode.getParentNode();
        }
        // Sets the new focus
        iFocusedNode = element;
    }

    /**
     * @see javax.microedition.m2g.SVGImage#getDocument()
     */
    public Document getDocument()
    {
        return iDocument;
    }

    /**
     * @see javax.microedition.m2g.ScalableImage#getViewportHeight()
     */
    public synchronized int getViewportHeight()
    {
        return iDocument.getViewportHeight();
    }


    /*
     * @see javax.microedition.m2g.ScalableImage#getViewportWidth()
     */
    public synchronized int getViewportWidth()
    {
        return iDocument.getViewportWidth();
    }

    /**
     * @see javax.microedition.m2g.SVGImage#incrementTime()
     */
    public void incrementTime(float seconds)
    {
        ((M2GSVGSVGElement)iDocument.getDocumentElement()).incrementTime(seconds);
    }

    /**
     * @see javax.microedition.m2g.ScalableImage#requestCompleted()
     */
    public void requestCompleted(String uri, InputStream resourceData) throws IOException
    {
        if (uri == null)
        {
            Logger.ELOG(Logger.EJavaUI,
                        "requestCompleted() throw NullPointerException");
            throw new NullPointerException(/*SF*/"The URI is null."/*SF*/);
        }

        if (resourceData != null)
        {
            byte receiveData[] = StreamUtils.readBytesFromStream(resourceData, -1);
            iDocument.requestCompleted(uri, receiveData);
        }
        else
        {
            // Indicates that the requested resource could not be
            // fetched by the ResourceHandler or application,
            // and in this event the SVG engine will not make further attempts
            // to load this resource.
            // Pass the null to the native side so it can delete the image
            iDocument.requestCompleted(uri, null);
        }
    }

    /**
     * Set document
     * @param aDocument -
     */
    public void setDocument(M2GDocument aDocument)
    {
        iDocument = aDocument;
    }

    /**
     * @see javax.microedition.m2g.ScalableImage#setViewportHeight()
     */
    public synchronized void setViewportHeight(int height)
    {
        iDocument.setViewportHeight(height);
    }

    /**
     * @see javax.microedition.m2g.ScalableImage#setViewportWidth()
     */
    public synchronized void setViewportWidth(int width)
    {
        iDocument.setViewportWidth(width);
    }

    //--------------------------------------------------
    //  STATIC METHODS
    //--------------------------------------------------
    /*
     * @see javax.microedition.m2g.SVGImage#createEmptyImage()
     */
    public static M2GSVGImage buildEmptyImage(ExternalResourceHandler handler)
    {
        try
        {
            return M2GSVGImage.buildImage(
                       new ByteArrayInputStream(
                           M2GSVGConstants.getInstance().iEmptySvgDocument.getBytes()),
                       handler, null, null);
        }
        catch (IOException e)
        {
            Logger.ELOG(Logger.EJavaUI, "M2GSVGImage: buildEmptyImage - IOEception: " + e.toString());
        }
        return null;
    }

    /**
     * Build svg image
     * @see javax.microedition.m2g.ScalableImage#createImage()
     * @param stream Plain text stream that contains svg data
     * @param handler External resource handler. If null then default
     * external resource handler is used.
     * @param baseUrl A base url from where a document is downloaded.
     * @param suffixUrl The suffix url according to the DRM opening mode of the SVG file
     * Null if it's not known.
     */
    public static M2GSVGImage buildImage(
        InputStream stream,
        ExternalResourceHandler handler,
        String baseUrl,
        String suffixUrl) throws IOException
    {
        if (stream == null)
        {
            throw new NullPointerException();
        }


        String strData = new String(StreamUtils.readBytesFromStream(stream, -1));

        // Default handler is used if the specified handler is null
        if (handler == null)
        {
            handler = M2GConnectionFactory.getExternalResourceHandler(null);
        }

        // Creates and setups svg image
        M2GSVGImage image = new M2GSVGImage();

        M2GDocument document = M2GDocument.buildDocument(
                                   image,
                                   baseUrl,
                                   suffixUrl,
                                   strData,
                                   handler);
        // Checks document validity

        image.setDocument(document);

        if (handler != null)
        {
            // Gets size of external resources
            int itemCount = _getExternalListSize(
                                document.getNativeSVGProxyHandle(),
                                document.getHandle());

            // Loops through external items
            for (int index = 0; index < itemCount; index++)
            {
                String url = _getExternalListItem(
                                 document.getNativeSVGProxyHandle(),
                                 document.getHandle(),
                                 index);
                // Calls an external implementation of the resource handler
                if ((url != null) && !(url.equals("")))
                {
                    document.invokeResourceHandler(url);
                }
            }
        }

        // initialise the viewport
        _initViewport(document.getNativeSVGProxyHandle(),
                      document.getHandle());


        return image;
    }

    /**
     * @see javax.microedition.m2g.ScalableImage#createImage()
     */
    public static M2GSVGImage buildImage(
        String url, ExternalResourceHandler handler) throws IOException
    {
        // Checks passed parameters
        if (url == null)
        {
            Logger.ELOG(Logger.EJavaUI,
                        "M2GSVGImage: 2 buildImage() - url is null");
            throw new NullPointerException();
        }
        if (url.length() == 0)
        {
            Logger.ELOG(Logger.EJavaUI,
                        "M2GSVGImage: 2 buildImage() - url is empty");
            throw new IllegalArgumentException();
        }
        // Default handler is used if the specified handler is null
        if (handler == null)
        {
            handler = M2GConnectionFactory.getExternalResourceHandler(url);
        }

        // Open the url and get input stream
        M2GSVGImage image = null;
        M2GConnectionProxy connectionProxy = null;
        try
        {
            connectionProxy = M2GConnectionFactory.create(url);
            image = M2GSVGImage.buildImage(
                        connectionProxy.getInputStream(),
                        handler,
                        connectionProxy.getBaseUrl(),
                        connectionProxy.getSuffixUrl());
            // Set connection policy
            if (image != null)
            {
                Document doc = image.getDocument();
                if (doc != null)
                {
                    ((M2GDocument)doc).setConnectionPolicy(
                        connectionProxy.getConnectionPolicy());
                }
            }
            return image;
        }
        finally
        {
            if (connectionProxy != null)
            {
                connectionProxy.close();
                connectionProxy = null;
            }
        }
    }

    //--------------------------------------------------
    // NATIVE METHODS
    //--------------------------------------------------
    private native static int _dispatchMouseEvent(
        int aSvgProxyHandle,int aDocumentHandle,
        int aX, int aY);

    private native static void _focusOn(
        int aSvgProxyHandle,int aDocumentHandle,
        int aSvgElementHandle);

    private native static void _focusOut(
        int aSvgProxyHandle,int aDocumentHandle,
        int aSvgElementHandle);

    native static int _getExternalListSize(
        int aSvgProxyHandle, int aDocumentHandle);

    native static String _getExternalListItem(
        int aSvgProxyHandle, int aDocumentHandle,
        int aIndex);

    private native static void _initViewport(
        int aSvgProxyHandle, int aDocumentHandle);
}