📄 ppsvgcanvas.java
字号:
/******************************************************************
* Copyright (C) 2002-2006 Andrew Girow. All rights reserved. *
* ---------------------------------------------------------------*
* This software is published under the terms of the TinyLine *
* License, a copy of which has been included with this *
* distribution in the TINYLINE_LICENSE.TXT file. *
* *
* For more information on the TinyLine, *
* please see <http://www.tinyline.com/>. *
*****************************************************************/
package com.tinyline.app;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;
import java.net.URL;
import java.util.zip.*;
import com.tinyline.tiny2d.*;
import com.tinyline.svg.*;
/**
* The <tt>PPSVGCanvas</tt> is the J2ME Personal Profile
* implementation of the SVG Canvas.
* <p>
* @author (C) Andrew Girow
* @version 1.11
* <p>
*/
public class PPSVGCanvas extends Canvas implements Runnable, ImageLoader,
org.w3c.dom.events.EventTarget
{
/** The canvas offscreen image */
Image bimg;
/** The canvas bounds */
int width,height;
/** The SVG renderer */
public SVGRaster raster;
/** The SVGImageProducer implementation */
PPSVGImageProducer imageProducer;
/** The events queue */
public SVGEventQueue eventQueue;
/** The events dispatching thread */
Thread thread;
/** The events listeners */
TinyVector listeners;
/** The base URL */
URL baseURL;
/** The current URL to go */
public String currentURL="";
/** True if the loading is finished */
boolean loaded;
/** The image cash */
Hashtable imageCash;
MediaTracker tracker;
/** The status bar */
StatusBar statusBar;
/**
* Constructs a new PPSVGCanvas instance.
*
* @param w The width of this canvas.
* @param h The height of this canvas.
*/
public PPSVGCanvas(int w, int h)
{
// Creates the SVG raster
TinyPixbuf buffer = new TinyPixbuf(w, h);
raster = new SVGRaster(buffer);
imageProducer = new PPSVGImageProducer(raster);
raster.setSVGImageProducer(imageProducer);
// Sets the SVG raster size and the color model
imageProducer.setColorModel(ColorModel.getRGBdefault());
// Sets the ImageLoader implementation needed for
// loading bitmaps
SVGImageElem.setImageLoader(this);
// Uncomment the following line for full antialiasing
raster.setAntialiased(true);
// Makes the events queues
eventQueue = new SVGEventQueue();
listeners = new TinyVector(4);
// Makes the image cash
imageCash = new Hashtable();
tracker = new MediaTracker(this);
}
/**
* Returns a TinyBitmap for the given image URL or path.
* @param imgRef The image URL or path.
* @return a TinyBitmap object which gets its pixel data from
* the specified URL or path.
*/
public TinyBitmap createTinyBitmap(TinyString uri)
{
String imgRef = new String(uri.data);
PPSVGBitmap bitmap = null;
try
{
URL url = new URL(baseURL,imgRef);
// check in the cash
bitmap = (PPSVGBitmap)imageCash.get(url);
// not found
if(bitmap == null)
{
bitmap = new PPSVGBitmap(tracker,url);
imageCash.put(url, bitmap);
}
}
catch (Exception ex)
{
}
return bitmap;
}
/**
* Creates a TinyBitmap which decodes the image stored in the specified
* byte array, and at the specified offset and length.
* @param imageData an array of bytes, representing
* image data in a supported image format.
* @param imageOffset the offset of the beginning
* of the data in the array.
* @param imageLength the length of the data in the array.
* @return a TinyBitmap object.
*/
public TinyBitmap createTinyBitmap(byte[] imageData, int imageOffset, int imageLength)
{
return new PPSVGBitmap(tracker,imageData, imageOffset, imageLength);
}
/** Starts the events dispatching thread */
public synchronized void start()
{
thread = new Thread(this);
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
}
/** Stops the events dispatching thread */
public synchronized void stop()
{
thread = null;
SVGEvent event = new SVGEvent(SVGEvent.EVENT_UNLOAD, null);
postEvent(event);
}
/**
* The events dispatching thread run()
*/
public void run()
{
Thread currentThread = Thread.currentThread();
try
{
while (currentThread == thread)
{
eventQueue.handleEvent(eventQueue.getNextEvent());
}
}
catch (InterruptedException e)
{
return;
}
catch( Throwable thr)
{
thr.printStackTrace();
alertError("Internal Error");
}
}
/**
* Loads and dispalys an SVG document from the given URL.
* External hyperlinks handling
*/
synchronized public void goURL(String url)
{
SVGEvent event = new SVGEvent(SVGEvent.EVENT_LOAD,url);
postEvent(event);
}
/**
* Returns the current SVGT document to its original view.
*/
public void origView()
{
SVGEvent event = new SVGEvent(SVGEvent.EVENT_ORIGVIEW, null);
postEvent(event);
}
/**
* Switches the rendering quality of this <tt>SVGPlayer</tt> .
*/
public void switchQuality()
{
SVGEvent event = new SVGEvent(SVGEvent.EVENT_QUALITY, null );
postEvent(event);
}
/**
* Suspends or unsuspends all animations that are defined
* within the current SVGT document fragment.
*/
public void pauseResumeAnimations()
{
SVGEvent event = new SVGEvent(SVGEvent.EVENT_PAUSERESUME, null );
postEvent(event);
}
/**
* This method is called when information about an image which was
* previously requested using an asynchronous interface becomes
* available. Asynchronous interfaces are method calls such as
* getWidth(ImageObserver) and drawImage(img, x, y, ImageObserver)
* which take an ImageObserver object as an argument.
*
* @param img the image being observed.
* @param flags the image status flags.
* @param x the <i>x</i> coordinate.
* @param y the <i>y</i> coordinate.
* @param width the width.
* @param height the height.
* @return <code>false</code> if the infoflags indicate that the
* image is completely loaded; <code>true</code> otherwise.
*/
public boolean imageUpdate(Image img, int flags, int x, int y, int width, int height)
{
if((flags & 0x30) != 0)
repaint(x, y, width, height);
return (flags & 0x60) == 0;
}
/**
* Updates this canvas
* @param g the specified Graphics context.
*/
public void update(Graphics g)
{
paint(g);
}
/**
* Paints this canvas
* @param g the specified Graphics context.
*/
public void paint(Graphics g)
{
if(bimg == null)
{
raster.sendPixels();
bimg = createImage(imageProducer);
}
if(bimg != null)
{
g.drawImage(bimg, 0, 0, this);
Toolkit.getDefaultToolkit().sync();// ????
}
}
/**
* The minimum size of the canvas.
*
* @return The minimum size of the canvas.
*/
public Dimension getMinimumSize()
{
return new Dimension(width, height);
}
/**
* The preferred size of the canvas.
*
* @return The preferred size of the canvas.
*/
public Dimension getPreferredSize()
{
return new Dimension(width, height);
}
/** Flushes the allocated resources. */
public void flush()
{
raster.flush();
if(bimg!= null)
{
bimg.flush();
bimg = null;
}
}
/**
* Loads an SVGT document from the given URL.
* @param urlStr The SVGT document URL or path.
* @return An SVGT document.
*/
public SVGDocument loadSVG(String urlStr)
{
// System.out.println(""+urlStr);
alertWait("Wait...");
InputStream is = null;
try
{
URL url = new URL(baseURL,urlStr);
baseURL = url;
is = url.openStream();
if(url.toString().endsWith("svgz"))
{
is = new GZIPInputStream(is);
}
}
catch( Exception ex)
{
//System.out.println("ioe" + ex);
alertError("Not in SVGT format");
}
return loadSVG(is);
}
/**
* Loads an SVGT document from the given InputStream.
* @param is The InputStream.
* @return An SVGT document.
*/
public SVGDocument loadSVG(InputStream is)
{
alertWait("Wait...");
String str = "";
loaded = false;
SVGDocument doc = raster.createSVGDocument();
int error;
try
{
// Read and parse the SVGT stream
TinyPixbuf pixbuf = raster.getPixelBuffer();
// Create the SVGT attributes parser
SVGAttr attrParser = new SVGAttr(pixbuf.width, pixbuf.height);
// Create the SVGT stream parser
SVGParser parser = new SVGParser(attrParser);
// Parse the input SVGT stream parser into the document
parser.load(doc,is);
str = "www.tinyline.com";
loaded = true;
alertInit(str);
}
catch(OutOfMemoryError memerror)
{
doc = null;
Runtime.getRuntime().gc();
alertError("Not enought memory");
}
catch(SecurityException secex)
{
doc = null;
alertError("Security violation");
}
catch( Exception ex)
{
//System.out.println("ioe" + ex);
doc = null;
alertError("Not in SVGT format");
}
catch( Throwable thr)
{
//System.out.println("ioe" + thr);
doc = null;
alertError("Not in SVGT format");
}
finally
{
try
{
if (is != null) is.close();
}
catch( IOException ioe)
{
//System.out.println("ioe" + ioe);
alertError(ioe.getMessage());
}
}
return doc;
}
/** Sets the status bar implementation */
public void setStatusBar(StatusBar aStatusBar)
{
statusBar = aStatusBar;
}
/** StatusBar: shows an alert */
public void alertError(String s)
{
if(statusBar!=null) statusBar.alertError(s);
}
/** StatusBar: shows a wait */
public void alertWait(String s)
{
if(statusBar!=null) statusBar.alertWait(s);
}
/** StatusBar: inits the bar */
public void alertInit(String s)
{
if(statusBar!=null) statusBar.alertInit(s);
}
//////////////////////////////////////////////////////////////////
/**
* Posts an event to the event queue.
*
* @param theEvent an instance of Event, or a
* subclass of it.
*/
public synchronized void postEvent(SVGEvent theEvent)
{
//IMPORTANT
theEvent.eventTarget = this;
eventQueue.postEvent(theEvent);
}
/*
* Methods inherited from interface org.w3c.dom.events.EventTarget
*/
/**
*
* <b>uDOM:</b> This method allows the registration of event listeners on the event target.
*
* @param type The event type for which the user is registering
*
* @param listener The listener parameter takes an interface implemented by the
* user which contains the methods to be called when the event occurs.
*
* @param useCapture If true, useCapture indicates that the user wishes
* to initiate capture. After initiating capture, all events of the
* specified type will be dispatched to the registered EventListener
* before being dispatched to any EventTargets beneath them in the tree.
* Events which are bubbling upward through the tree will not trigger an
* EventListener designated to use capture.
*/
public void addEventListener(java.lang.String type,
org.w3c.dom.events.EventListener listener,
boolean useCapture)
{
listeners.addElement(listener);
}
/**
*
* <b>uDOM:</b> This method allows the removal of event listeners from the event target.
*
* @param type Specifies the event type of the EventListener being removed.
* @param listener The listener parameter indicates the EventListener to be removed.
* @param useCapture Specifies whether the EventListener being removed was
* registered as a capturing listener or not.
*/
public void removeEventListener(java.lang.String type,
org.w3c.dom.events.EventListener listener,
boolean useCapture)
{
int i = listeners.indexOf(listener,0);
if(i>0)
{
listeners.removeElementAt(i);
}
}
/**
* <b>uDOM:</b> This method allows the dispatch of events into the implementations event model.
* Events dispatched in this manner will have the same behavior as events dispatched
* directly by the implementation.
*
* @param evt Specifies the event type, behavior, and contextual
* information to be used in processing the event.
* @return The return value of dispatchEvent indicates whether
* any of the listeners which handled the event called preventDefault.
* If preventDefault was called the value is false, else the value is true.
*/
public boolean dispatchEvent(org.w3c.dom.events.Event evt)
{
org.w3c.dom.events.EventListener h;
for(int i=0; i < listeners.count; i++)
{
h = (org.w3c.dom.events.EventListener)listeners.data[i];
if(h!=null) h.handleEvent(evt);
}
return true;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -