12. Scalable Vector Graphics

YOU can do some jazzy stuff with images using the Game API, but images have some significant shortcomings on small devices:

  • Images cannot be resized in MIDP. Your application is likely to run on devices with different screen sizes. While it is possible to construct resizable screens at runtime from a handful of images, it’s a little tricky.

  • Images cannot be rotated by arbitrary amounts. Although you can mirror images and rotate them in increments of 90 degrees, MIDP does not offer anything fancier. This limitation makes sense, because small devices are not usually equipped with the memory and processing power to perform these types of transformations on images.

  • Images are not an efficient representation of some pictures. For some pictures, it makes more sense to describe the picture (a vector format) than to describe every pixel in an image (a raster format).

  • Images do not allow for the easy manipulation of the elements of a picture.

These shortcomings are addressed by JSR 226, the Scalable 2D Vector Graphics API for J2ME. Scalable Vector Graphics (SVG) is a kind of XML for describing pictures. Because it is essentially a programming language, SVG can also describe animations and user interactions. JSR 226 is a standard API for displaying and manipulating SVG documents.

The JSR 226 SVG API applies to a specific subset of SVG called SVG Tiny. SVG and SVG Tiny are both defined by the World Wide Web Consortium. This chapter is not about SVG itself. For more information, consult the specifications:

http://www.w3.org/TR/SVG11/
http://www.w3.org/TR/SVGMobile/

In most cases, a graphic artist will create SVG documents. You probably will not have to know anything about SVG documents except for the IDs of different pieces of the document. Some information about authoring tools is available here:

https://meapplicationdevelopers.dev.java.net/uiLabs/Tools.html

As of September 2007, 28 devices are shipping with JSR 226. As part of the MSA subset, however, JSR 226 should become much more widely distributed in the near future. A list of JSR 226 devices is here:

http://svg.org/special/226_phones

The SVG API is relatively small. A half dozen classes and interfaces in javax.microedition.m2g supply tools for rendering and manipulating SVG documents. The rest of the API, in org.w3c.dom and two subpackages, represents the structure of an SVG document.

12.1. The Simplest Way to Show SVG Content

The simplest possible case is that you just want to display an SVG file. Your graphic artist generates the file and all you want to do is stick it on the screen.

In this case, your best friend is SVGAnimator. SVGAnimator takes care of a lot of details for you and just hands you a Canvas that you can put on the device’s display.

Before you can create an SVGAnimator, you must first load an SVG document with SVGImage. SVGImage inherits two static creation methods from its parent class, ScalableImage.

Image

The ExternalResourceHandler knows how to retrieve any content that is referenced from within the document. You can supply null, in which case the device tries to do something reasonable to locate external resources.

If you plan to use SVG documents that reference external resources that are part of your MIDlet suite JAR file, you must supply an implementation of ExternalResourceHandler that retrieves the external resources from the JAR file. You have to supply a requestResource() method that obtains an InputStream for a given URI. The InputStream should be passed back to the image’s requestCompleted() method.

If you point one of the createImage() methods at an SVG document, the returned object will of course be an SVGImage. To load an SVG document from the MIDlet suite JAR file, you could do something like this:

Image

The image has a viewport, which is simply the size in pixels that is used to display the image. In general, you will want to fill the available screen space, but you don’t know how much that is until later when you get a Canvas.

Once you’ve got the image, creating an SVGAnimator is easy.

Image

To get the Canvas that shows the image, call getTargetComponent() and cast the result to Canvas. The SVG API is designed to be flexible enough to run on Connected, Limited Device Configuration (CLDC) devices as well as on Connected Device Configuration (CDC) devices, so the return type of getTargetComponent() is deliberately vague. This means that the SVG API can be used in a variety of GUI environments. In the MIDP world, though, the return value will always be a Canvas.

If the SVG document you are displaying contains animation, you can tell the SVGAnimator to show it by calling play(). The animation runs until you call pause() or stop(). The example in the next section demonstrates how to correctly handle animations.

Here is a complete example that loads an SVG document and displays it.

Image

Figure 12.1 shows the result in Sun’s emulator. The document is a picture of Duke, the Java platform mascot.

Figure 12.1. The SimplePlayerMIDlet example

Image

12.2. Working with Animated Documents

The previous MIDlet is fine for showing static content, but part of the fun about SVG is documents that move. The thumbsUp-spin.svg document from the previous example includes an animation, but SimplerPlayerMIDlet just shows a single still frame.

You need to kick off SVGAnimator with the play() method. That’s easy enough, but finding the right place to call play() is a challenge. Ideally, you would call play() from the showNotify() method of the Canvas. The problem is that the Canvas comes from the SVGAnimator and you can’t override the showNotify() method.

Fortunately, you can supply an SVGEventListener to the SVGAnimator. This listener receives the usual Canvas-like event notifications, such as key events, pointer events, showNotify(), and hideNotify().

The next example, SimpleAnimatorMIDlet, demonstrates this technique. The MIDlet itself is an SVGEventListener. When the associated Canvas is shown, the animation is played, and when the Canvas is hidden, the animation is paused.

Furthermore, SVGAnimatorMIDlet makes the Canvas full-screen and removes the Exit command. Instead, hit any key to exit the MIDlet.

Image

Image

On Sun’s emulator, Duke will spin around jauntily (see Figure 12.2). Just hit a key to exit the application.

Figure 12.2. Whoa, Dukey!

Image

12.3. Digging into an SVG Document

SVG documents can be accessed and manipulated using the org.w3c.dom.svg package. For the most part, its interfaces extend the standard DOM interfaces in org.w3c.dom and org.w3c.dom.event.

The fundamental interface for SVG documents is SVGElement. It contains methods for getting and setting traits, which means you can make modifications to an SVG document on the fly. SVGAnimator is smart enough to detect changes to a document and update the screen.

Once you’ve loaded an SVGImage, call getDocument() to retrieve the document. You can then retrieve the top-level element (an instance of SVGSVGElement) with getDocumentElement(), or search for a specific element with getElementById().

For example, the SVG document in the previous example contains one element that defines the trademark symbol (TM). Here is the beginning of the element definition for the trademark symbol.

Image

To find the SVGElement for the trademark symbol, all you have to do is this:

Image

Once you’ve got an interesting SVGElement, you can have all sorts of fun. You can retrieve traits as text. This example retrieves the current transformation of the element:

Image

You can also retrieve traits into more specific data types. The org.w3c.dom.svg package includes five handy data type classes: SVGMatrix, SVGPath, SVGPoint, SVGRect, and SVGRGBColor. If you wanted to deal with the element’s transformation as a matrix rather than a string, you could do this:

Image

SVGElement has a corresponding set of set methods so that you can assign element traits using either strings or the more complex data types.

To rotate the trademark symbol around the point 182, 172, do this:

Image

TMTweakerMIDlet is identical to SimplePlayerMIDlet except for showSVGImage(), which contains extra code to rotate the trademark symbol:

Image

On Sun’s emulator, the result looks like Figure 12.3.

Figure 12.3. TMTweakerMIDlet rotates the trademark symbol.

Image

If you plan to modify an SVG document while the SVGAnimator is playing, you should take care to make those modifications in the animator’s thread. Use invokeLater() and invokeAndWait() for this purpose. Each method takes a Runnable object whose run() method is called by the animator’s thread. invokeLater() returns immediately, while invokeAndWait() will not return until the Runnable has been run.

12.4. Displaying an SVG Document on Your Own Canvas

SVGAnimator creates a Canvas whose sole purpose in life is to display an SVG document. If you’d prefer, you can create your own Canvas and use part of it to display the SVG document.

The magic that makes it possible is ScalableGraphics, which knows how to render an SVGImage on a Graphics object. To get one, call the static factory method createInstance().

Image

Inside your paint() method, you have to bind the ScalableGraphics to the Graphics you are using.

Image

Then render as many SVGImages as you wish. You have to specify where you want the image. The width and height of the image are determined by its viewport width and height.

Image

When you’re finished, let the ScalableGraphics know that it doesn’t need the Graphics any more.

Image

It’s prudent to place releaseTarget() inside a finally clause. Even if something goes wrong in render(), you must release the ScalableGraphics.

Here is a canvas that frames an SVGImage with a border of blue diamonds (see Figure 12.4).

Figure 12.4. It’s easy to show SVG documents in your own canvas.

Image

Image

The code having to do with showing an SVG document is minimal, just one line in the constructor and three in paint().

12.5. Creating New SVG Elements

To add new elements to a document, first obtain the document element and the root element as SVGSVGElement.

Image

Now you can create an element with the Document’s createElementNS() method. Set attributes on the new element with the setTrait() methods.

Image

To add the newly created element into the document, use appendChild() or insertBefore() on the root element.

Image

Updates to a playing document should be made in the SVG document update thread. SVGAnimator includes invokeAndWait() and invokeLater() methods for this purpose. You have to create a Runnable to do some work, then pass the Runnable to invokeAndWait() or invokeLater() to get the job done in the correct thread.

It is also possible to create an entirely new SVG document. If you want to explore this topic further, take a look at CreateEmptyImageDemo, one of the MIDlets in SVGDemo, an example bundled with the Sun Java Wireless Toolkit.

The following example, BubblesMIDlet, shows how to add new elements to an existing image. It is an adaptation of SimpleAnimatorMIDlet, so it uses a full-screen Canvas. Hit any key to exit the application.

Image

Image

Image

Image

When run on Sun’s emulator, it looks like Figure 12.5.

Figure 12.5. Adding new elements to an SVG document

Image

12.6. SVG Event Handling

You have already seen how to capture Canvas-related events in your application by using an SVGEventListener. In addition, SVG documents themselves can respond to a few kinds of events. The SVGImage class contains corresponding methods.

  • activate() delivers a DOMActivate event to the document.

  • dispatchMouseEvent() tells the document that a pointer event has occurred.

  • focusOn() delivers a DOMFocusIn event to the specified SVGElement. It also delivers a DOMFocusOut event to the element that previously had the focus.

  • incrementTime() sets the time used for animations.

If you are displaying an SVG document with a playing SVGAnimator, incrementTime() is automatically called, so a document with animations will play automatically. If you are displaying an SVG document using ScalableGraphics, you must call incrementTime() yourself to animate the document.

You must call the other event methods yourself if you need the SVG document to respond to them. Because few MIDP devices support pointer events, you might need to provide an alternate method for simulating pointer events. The only type of pointer event you can deliver to SVGImage is a click with x and y coordinates, like this:

Image

The x and y coordinates are in the viewport coordinate system, which might not be the same as the Canvas’s coordinate system.

The next example shows one way to move focus in a document. Hitting keys toggles the focus between the trademark symbol and Duke. The example document, thumbsUp-enhanced.svg, defines some behavior that swells up the trademark symbol when it has focus and shrinks it back down when it loses focus.

Image

Image

Image

When you run this example, you’ll see the SVG document of Duke as usual. Hit any arrow key, or the select key, to change the focus. As the trademark symbol gains and loses focus, you’ll see it grow and shrink. When Duke gains focus, he jumps up, and when he loses focus, he falls back down. In the screen shot, the MIDlet has just called focusOn() for the trademark symbol (see Figure 12.6). Hit any other key to exit.

Figure 12.6. Triggering focus events in a document

Image

12.7. Summary

SVG is a way of describing pictures using XML. It is good for small devices because images can be easily scaled and transformed to fit the available space, and the document files can be compact. The JSR 226 SVG API provides classes for displaying and manipulating SVG documents. SVGImage can be used to load an SVG document. SVGAnimator knows how to display and animate an SVGImage. The SVG API also includes a DOM API that you can use to examine and modify SVG documents. In addition, SVGImage includes methods that allow your application to deliver events to an SVG document. For interactive animations that scale easily to different screen sizes, SVG is hard to beat. The JSR 226 SVG API includes everything you need to work with SVG Tiny documents.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.128.205.21