Tools of the Trade: Flash meets Java with Transform SWF and JFlashPlayer

Contents

Article Description

Perhaps some of your Java applications can benefit from supporting Flash. Jeff Friesen introduces two tools that support Flash in a Java context: Transform SWF and JFlashPlayer. Transform SWF is useful for creating new Flash movies and updating existing Flash movies. JFlashPlayer gives you the ability to integrate a Flash movie player into your software. In this article, you're introduced to three Java applications that show you how to use these nifty tools.

Many people believe that Macromedia’s Shockwave Flash (SWF) file format
is the best way to present feature-rich and low-bandwidth animated
content—Flash movies—over the Web. In light of this belief,
it’s not surprising that Macromedia’s Flash movie players have been
installed (mainly in Web browser contexts) on millions of computers around the
world. This huge potential audience is a great incentive for you to distribute
your electronic books, video-based tutorials, and other kinds of multimedia
documents as Flash movies.

Java’s combination of power and simplicity has made it a very popular
programming language and environment; the amount of Java-based software for the
server and desktop continues to grow. Perhaps some of your Java software can
benefit from supporting Flash. For example, a Web application creates a
user-specific Flash movie and sends that movie to the user’s Web browser
when the user contacts the application. Another example: a complex desktop
application contains a Flash movie player that plays a tutorial movie when a
user requests help.

I have discovered many tools that support Flash in a Java context. This
article introduces two of those tools to you: Transform SWF and JFlashPlayer.
Transform SWF is useful for creating new Flash movies and updating existing
Flash movies. In contrast, JFlashPlayer gives you the ability to integrate a
Flash movie player into your software. As you read this article, you’re
introduced to three Java applications that show you how to use these tools.

NOTE

I developed and tested this article’s Java applications using J2SE 5.0
(via Sun’s SDK command-line tools), Transform SWF 2.0.4, and JFlashPlayer
1.5. Windows 98 SE was the underlying platform. You can download the code
here.

Create and update Flash movies with Transform SWF

Flagstone Software
makes available three open-source tools for creating and updating Flash movies.
Transform SWF is the foundation tool in this tools suite. Each of the other
higher-level tools depends on Transform SWF. Although you can use Transform SWF
(and the other tools) without paying a fee, this software is licensed under the
BSD license. Make sure you fully understand your responsibilities, as stipulated
by this license, before integrating Transform SWF (and the other tools) with
your own software.

Before we can explore Transform SWF, we need to download and install that
tool. Accomplish the download task by pointing your Web browser to Flagstone
Software’s
Downloads for Java
Web page and clicking the link to the appropriate Transform SWF distribution
file. For example, I downloaded transform-java-2.0.4.zip. After
downloading the distribution file, you should verify the integrity of that file
by also downloading the corresponding PGP or MD5 signature and using the
appropriate PGP, GPG, or MD5 tool to perform the verification task. The
Downloads for Java Web page provides instructions on how to accomplish this task
with PGP.

After downloading and unzipping the Transform SWF distribution file, you need
to install that tool. Begin by creating an appropriate directory structure to
facilitate project development. For example, I created an fss umbrella
directory in the root directory on my C: drive (so that I could accommodate
Flagstone’s other open-source tools in the future) and moved Transform
SWF’s home directory to fss. I also placed a projects
directory in fss to conveniently organize my Transform SWF projects.
The following directory structure emerged:

c:\fss\transform-java-2.0.4
c:\fss\projects

Transform SWF’s directory contains a Jar file: transform.jar.
To finish installing this tool, add that Jar file to the CLASSPATH environment
variable. For Windows 98 SE, the command to set CLASSPATH in the context of the
preceding directory structure is set
classpath=c:\fss\transform-java-2.0.4\transform.jar;%classpath%;.. If you
are using a different version of Windows or a non-Windows operating system,
study your OS documentation to find out how to set this environment
variable.

Now that Transform SWF has been installed, let’s investigate this tool.
For starters, Transform SWF is a collection of Java classes that implement the
various tags and other data structures described by Macromedia’s SWF
file-format specification. These classes fully support this specification up
through Flash MX 2004 (version 7) and are stored in package
com.flagstone.transform, which corresponds to the
transform.jar Jar file.

Assuming the previously created directory structure, point your Web browser
to c:\fss\transform-java-2.0.4\doc\datasheets\index.htm, to explore
Javadoc documentation for this package and its classes. Because it is beyond
this article’s scope to delve into SWF, I recommend reading the package
description, especially if you are new to SWF. That description concisely
describes SWF, with emphasis on Flash’s programming model.

The central class in the Transform SWF package is FSMovie. That
class describes a Flash movie in terms of header information, such as the size
of each movie frame—measured in twips (one twip equals 1/20th of
a point or 1/1440th of an inch)—and the number of frames that are shown
per second, and a sequence of objects that correspond to the various tags
comprising the movie.

The simplest way to create a Flash movie is to first create an
FSMovie object (initially empty of tag objects) by invoking the
public FSMovie()constructor, then create objects representing various
tags and add them to the FSMovie object, and finally invoke
FSMovie’s public void encodeToFile(String filename)
method to encode the movie to the SWF file identified by filename. (It
would be a good idea to ensure that the filename ends with a .swf
extension.) Because encodeToFile() is capable of throwing
java.io.IOException if it cannot create or write to the file,
you’ll need to address this possibility in your code. The following code
fragment demonstrates these methods and more as it creates a very simple Flash
movie:

After creating an FSMovie object devoid of any tag objects, the code
fragment invokes FSMovie’s public void setFrameSize(FSBounds
bounds) method to set the size (400x400 twips) of all movie frames via an
FSBounds object and invokes public void setFrameRate(float
fps) to establish the recommended number of frames (1) to play per second.
Of course, we would not need to invoke these methods if we created the
FSMovie object with the public FSMovie(FSBounds bounds, float
fps) constructor.

Moving on, the code fragment introduces a SetBackgroundColor tag
into the movie, which identifies the color of each frame’s background (in
many movies, the background color might or might not appear, depending on how
much of each frame is covered by various shapes). The tag is introduced by first
creating an FSColor object representing opaque color blue (there is no
transparency information), then passing that object to a newly-created
FSSetBackgroundColor tag object, and finally adding that tag object to
the FSMovie object by invoking FSMovie’s public void
add(FSMovieObject object) method—FSMovieObject is an
abstract class that serves as the superclass of tag classes (such as
FSSetBackgroundColor).

After adding the FSSetBackgroundColor tag object to the
FSMovie object, the code fragment invokes encodeToFile() to
create the SWF movie file. That method creates test.swf, encodes
FSMovie’s header information and tag objects to the equivalent
SWF binary tags, and outputs that binary information to the file. If something
goes wrong during file creation or file writing, an IOException throws;
the code fragment outputs the exception information to the console.

If you were to view test.swf in a Flash movie player, you would see
a very short movie consisting only of a blue background. For a more complex
movie, you need to incorporate additional Transform SWF classes into a
movie-creation Java application. To that end, I prepared an example that
demonstrates a few Transform SWF classes. This example’s
CreateSquareCircle.java source code appears in Listing 1.

The most interesting parts of Listing 1 involve the creation and animation of
the square shape. That shape is created as an FSShape object, and this
object and other relevant objects are stored in an FSDefineShape tag
object, which represents a DefineShape tag that is responsible for
making the square shape available to the movie.

The FSShape object is a container for FSShapeStyle,
FSLine, and FSCurve objects. In Listing 1, only one
FSShapeStyle object (which identifies the line-style and
fill-style—via one-based indices into arrays passed to
FSDefineShape—and initial drawing position of the shape) and four
FSLine objects (whose coordinate arguments are relative to the current
drawing position) are added to the FSShape object. After the
FSShape object has been populated, an FSDefineShape tag object
is created with a unique identifier (for later reference by the
FSPlaceObject tag object), an FSBounds object that specifies
the size of the shape (in twips), previously created
java.util.ArrayLists that specify the shape’s line-styles and
fill-styles (only one of each style is created), and the FSShape
object.

The square is animated by adding a sequence of FSPlaceObject,
FSShowFrame, and FSRemoveObject tag objects to the
FSMovie object:

The FSPlaceObject tag object represents a PlaceObject tag
that is responsible for placing the square shape onto the movie player’s
display list (a layered data structure that controls the order by which
shapes are displayed on the screen). The first argument passed to the
constructor identifies the square’s FSDefineShape tag object, the
second argument identifies the layer in which the square will be placed (shapes
placed at higher-numbered layers are rendered over shapes placed at
lower-numbered layers), and the last two arguments identify the location (in
twips relative to the upper-left corner of the movie’s frame window) where
the shape’s upper-left corner will be placed. Listing 1 calculates this
location using sines and cosines, so that the square travels in a circle around
the movie player’s window.

The FSShowFrame tag object represents a ShowFrame tag that
is responsible for rendering the contents of the display list onto the movie
player’s window. Lower-numbered layers are rendered first; higher-numbered
layers are rendered last.

The FSRemoveObject tag object represents a RemoveObject
tag that is responsible for removing the square shape from the display list.
This shape must be removed before it can be repositioned. The first argument
passed to the constructor identifies the square shape; the second argument
identifies that shape’s layer.

So what does the movie look like? Figure
1 reveals a single frame in the
FireFox Web browser’s integrated movie player’s window that shows
the square in transit.

Suppose that you have access only to squarecircle.swf and want to
change the square’s fill color to blue. How would you update that
movie’s SWF file? Transform SWF provides a solution, which is demonstrated
in Listing 2’s UpdateSquareCircle.java source code.

The FSMovie class provides the public FSMovie(String
filename) constructor for reading the contents of the SWF file identified
by filename into an FSMovie object. After creating that
object, you can call either of FSMovie’s public ArrayList
getObjects() or public ArrayList getObjectsOfType(int type)
methods to retrieve movie tags as objects—the first method returns an
ArrayList of all tag objects, and the latter method returns an
ArrayList of only those tag objects that match the specified
type, as denoted by the FSMovieObject class
(FSMovieObject.DefineShape, for example). After you have the
ArrayList, you can iterate through that container object until you find
the desired tag object.

Listing 2 invokes getObjectsOfType() to return an ArrayList
of all FSDefineShape tag objects. Because there is only one
DefineShape tag in squarecircle.swf, Listing 2 doesn’t
need to search the array for the appropriate FSDefineShape tag object.
Instead, after creating an appropriate ArrayList to store the new solid
blue fill-style, the source code invokes FSDefineShape’s
public void setFillStyles(ArrayList fillStyles) method to change the
fill-styles associated with the ArrayList’s solitary
FSDefineShape tag object.

Compile UpdateSquareCircle.java and run the resulting application.
Start up a Flash movie player and play squarecircle.swf. You will
discover a blue square moving in a circular fashion.