This page contains some documentation that was previously hosted on the now defunct OSFlash wiki. It is rather old, disorganised and unhelpful. Sorry :(.
Homepage: http://swfmill.org/
License: GNU General Public License
swfmill is a command line XML to SWF to XML processor using SWFML, an XML vocabulary closely modeled after the SWF format. It i.e. it does not check if shapes you draw are closed, etc., so make sure to thoroughly test SWFs you make with it. Unlike the “simple” vocabulary, “basic” (like SWF) uses twips as a unit instead of pixels. 20 twips are one pixel.
If you don't like the “simple” vocabulary or have some special requirements you can use it to transform your own XML vocabulary to “basic” SWFML and output an SWF. Technically, “simple” is a built-in default transform that does just that. There are some SWF specific extensions to manage IDs and to import other SWFs.
You can download windows and OS X and the sources for Linux. 64 bit processors are supported since version 0.2.3.
Please follow the links at the bottom of this page for some examples and documentation, and visit the homepage.
There used to be, but OSFlash closed down and took the mailing list with it.
You might be able to read the mailing list archive on archive.org.
swfmill was originally written by Daniel Turing, but is now sporadically maintained by Daniel Cassidy. It includes substantial contributions by Ralf Fuest, Steve Webster and others.
That's the most basic SWF you can make. It's 320 by 240 pixels,
tries to run at 12 frames per second, and has a white background.
Note the <frame/>
tag, except of the
<movie/>
and <background/>
tags, all other tags belong into one. For simplicity's sake, most
examples below will assume you know that, and won't include the
header explicitly.
<?xml version="1.0" encoding="iso-8859-1" ?>
<movie width="320" height="240" framerate="12">
<background color="#ffffff"/>
<frame/>
</movie>
If you save this XML code into a file sample.swfml
(it could also be sample.xml
or in fact anything
else), you can compile it into a binary SWF with the following
commandline:
swfmill simple sample.swfml sample.swf
The <clip/>
tag lets you import JPGs, PNGs
(including alpha), SWFs and SVGs (somewhat experimental). They
will be available as MovieClips. This example will import
library/foo.jpg
and give it the ID foo
.
swfmill can also import TrueType fonts, but the syntax is different.
<frame>
<clip id="foo" import="library/foo.jpg"/>
</frame>
The <library/>
tag, like almost all others,
lives in a <frame/>
tag. You can determine
in which frame assets are included into your SWF by using
multiple frames and putting it into the one you want your assets
to be available in. You don't have to import assets into the
library, but then they won't be available to ActionScript.
Sometimes you don't need an asset to be in the library, because
you only want to use it as a part of another clip you define,
or you place it onto the stage directly with the
<place/>
tag.
Of course, you can have several <clip/>
and
<font/>
tags in one
<library/>
. The example will import the same
image as above, but this time into the library. The ID also
serves as the linkage name if you import into the library.
<frame>
<library>
<clip id="foo" import="library/foo.jpg"/>
</library>
</frame>
swfmill can import most TTF fonts, with exception to fonts that use Bezier curves and bitmap fonts. It supports both DefineFont2 (>= Flash 7) and DefineFont3 (>= Flash 8).
Importing TTF fonts works almost like importing images or SWFs,
but the <font/>
tag is used.
Consider the following example:
<?xml version="1.0" encoding="iso-8859-1" ?>
<movie version="7" width="320" height="240" framerate="12">
<frame>
<library>
<font id="verdana" import="verdana.ttf" name="verdana"/>
<font id="verdanab" import="verdanab.ttf" name="verdanab"/>
</library>
</frame>
</movie>
Note : That the font tag must exist inside a library tag for the linkage id to work with TextFormats and dynamically created TextFields, or that it is Exported for runtime sharing.
On the movie tag, if version="7" DefineFont2 is created. If version=“8” or higher, DefineFont3 is created. Accordingly, changing the version attribute will also change the font rendering engine which flash uses.
By default, swfmill pulls the font name from the TTF internal fields. This may create font name conflicts if you have different styles of the same font. To avoid this problem, include the name attribute. Without it, fonts such as Verdana Regular and Verdana Bold will both have the default name “Verdana”: allowing you access to only 1 of those fonts in your text fields.
glyphs == characters and swfmill allows you the option to include some or all of the characters provided by a TTF. We do this with the glyphs attribute.
If you do not include the glyphs attribute on the font tag, all available glyphs will be imported. This is a feature for users who want the most complete font they can get.
Other users may find this as a hindrance because they only need certain characters and want to keep the output SWF small. In this case, you can list the glyphs you would like included in the glyphs attribute. For example:
<font id="verdana" import="verdana.ttf"
name="verdana" glyphs="ABC "/>
You may need to include special characters in your glyphs tag. You can do this by using XML entities or Unicode's Universal Character Set format. Note that XML only supports &, > <, ", and '. All other characters will need to be referenced in the Universal Character Set format. The following example includes the uppercase inverted exclamatory mark (¡), the ampersand symbol (&), and the greater than symbol (>), and the uppercase A.
<font id="verdana" import="verdana.ttf"
name="verdana" glyphs="¡&>A" />
The font node has two differing attributes “id” and “name”. id is used for the format attribute of textfields:
<textfield id="hellobox" width="200"
height="50" size="10" font="verdanab"
text="hello world!"/>
<place id="hellobox" name="output" depth="10"/>
The name attribute is used in order to get an ActionScript
reference to the embedded font. When using the TextField's
embedFonts property, you'll be able to use the
TextFormat.font
property with this name.
This attribute is also a way to group different font by families and retrieve them from actionscript (Flash 8 only).
id and name attributes can be used together to serve different purposes.
We can import sounds with a similar method, where “id” is the linkage id, and we put the following tag inside of the <library> tag:
<sound id="myID" import="blah.mp3"/>
and later in our actionscript (compiled prior via Mtasc, etc). we'd put:
var snd:Sound = new Sound();
snd.attachSound("myID");
snd.start();
Note: Requires pre-release 0.2.11.18 or later, and sound is not streamed.
Note: Works with 56, 64, 128, 192 and 256 kbps MP3s.
Note: joint stereo MP3s, WAV etc don't play at all.
You can use shared libraries, too. SWFs created with swfmill always are available for runtime sharing, to import another SWF as a library keep a local copy for testing purposes and import it like this:
<import file="library/library.swf"
url="http://foo.com/library.swf"/>
The class
attribute of the <clip/>
tag can be used to assign a class to your MovieClips. If you're
doing this, keep in mind that MTASC does not compile “unused”
classes into your SWF, and it has no way of knowing you need
them for this. You can “force” it to include the class by assigning
it to a variable or adding the class to the mtasc command line
explicitly, but a simple import
won't be enough. As
usual when you do this, make sure that your class inherits from the
intrinsic MovieClip
class. In order for swfmill to
find the class it must have been compiled previously. That means
you don't run swfmill first and compile your classes into it
afterwards, but compile a classes.swf
(although any
other name would do) first with mtasc's -header
setting and import it in your swfml:
<frame>
<clip import="classes.swf" />
<library>
<clip id="foo" import="library/foo.jpg" class="org.osflash.Foo"/>
</library>
</frame>
As for version 0.2.9 you are able to use the new component tag. No need to use a library and a call tag. Here is a simple example. The combo is instantiated later by actionscript injected using mtasc.
<background color="#ffcccc"/>
<frame>
<component id="ComboBox" file="swc/ComboBox/ComboBox.swf"/>
<frame/>
There are still 2 problems with components:
SWF extracted from a SWC can be big because they contain data for the Flash IDE, classes and the visual elements that we need.
If you add a couple of components from the same family, swfmill will not check if some classes already exist and you will end up with duplicates.
Here is a comparison with 3 components of the same family, an Alert window, a Label and a ProgressBar:
Compiled with the Flash IDE: 12k
Compiled with swfmill: 99k
To publish a Flash 8 SWF using Swfmill, specify the player version in the movie tag like this:
<movie version="8" width="550" height="400" framerate="31">
Also, if you are compiling AS2 code for use in your SWF with MTASC,
make sure you compile it with the -version 8
switch.
Since swfmill version 0.2.11.3, some of the new tags introduced in flash 8 were introduced. Here is a list of them:
- File attributes to set security sandbox file access and metadata :
<FileAttributes hasMetaData="0|1" useNetwork="0|1" />
Choose between the arguments separated by |. By default, useNetwork is set to 0 which means 'filesystem' (1 means 'network'). But make sure to add to the <movie> root tag the attribute local-access like so:
<movie width="550" height="400"
framerate="40" version="8"
local-access="filesystem|network">
- Metadata that search engine could index :
<meta title="my title" description="To be indexed" />
- Flash 8 filters and blending modes. Shared library published to flash 8 are now correctly handled.
By default, swfmill publishes AS2 based AVM1 movies, which is not
fully compatible with AVM2 that runs AS3. To publish AVM2
compatible SWF files for use in your AS3 projects, add the
attribute as3="1"
to your movie tag:
<movie version="9" width="550" height="400"
framerate="31" as3="1">
Sometimes you need movie clips which contain multiple states. Probably the most common example of this is a button. Buttons will normally have 4 states, Up, Over, Down, and Disabled. You can create a MovieClip that contains all the states for a button, and then have an ActionScript class manage the events and change which state is displayed depending on the state the button is in.
Here's an example of one way to create such a clip:
<movie width="320" height="240" framerate="12" version="7">
<clip id="upState" import="up.png"/>
<clip id="downState" import="down.png"/>
<clip id="overState" import="over.png"/>
<clip id="disabledState" import="disabled.png"/>
<frame>
<library>
<clip id="testButton">
<frame name="Up">
<place id="upState"depth="1"/>
<stop/>
</frame>
<frame name="Over">
<place id="overState" depth="2"/>
<stop/>
</frame>
<frame name="Down">
<place id="downState" depth="3"/>
<stop/>
</frame>
<frame name="Disabled">
<place id="disabledState" depth="4"/>
<stop/>
</frame>
</clip>
</library>
</frame>
</movie>
To change which state is displayed you can simply do a
gotoAndStop(name)
call on the button's movie clip.
There is one problem with the above solution. If your state images have transparencies then latter states could end up showing parts of the previous states. In theory you could set the depth values of the clips in all 4 frames to the same value, but this doesn't seem to work for more than 2 frames (at least as of 0.2.12.2).
To get around the transparency problem you could also define your movie clip as follows:
<movie width="320" height="240" framerate="12" version="7">
<clip id="upState" import="up.png"/>
<clip id="downState" import="down.png"/>
<clip id="overState" import="over.png"/>
<clip id="disabledState" import="disabled.png"/>
<frame>
<library>
<clip id="testButton">
<frame>
<place id="upState" name="Up" depth="1"/>
<place id="overState" name="Over" depth="2"/>
<place id="downState" name="Down" depth="3"/>
<place id="disabledState" name="Disabled" depth="4"/>
</frame>
</clip>
</library>
</frame>
</movie>
In this case you could simply have your code show/hide the child clips by name depending on which state you want displayed. It's a little more work in the code to change states (you have to both show the state you want and hide the others) but you don't have to worry about one state 'seeing through' to another.
'Place' tag is used to insert clips to the SWF timeline. Clips themselves can contain frames and you use 'place' for them as well.
<frame>
<place id="red" x="64" y="64" depth="0"/>
</frame>
Along with the identifier and the optional coordinates, you must enter the depth for the clip. Depth starts from zero and up, where the highest number comes out top. Two clips cannot reside at the same depth, and when assigned, one will replace the other.
It's important to keep in mind that once a clip has been assigned to a depth, it will occupy that depth for the rest of the remaining timeline. Meaning that a clip placed at frame one will stay there for the rest of the movie. The only way to remove a clip is to assign another clip to its reserved depth, effectively overwriting it from the timeline.
<frame>
<place id="red" x="64" y="64" depth="0"/>
</frame>
<frame>
<!-- overwrite red from depth="0" with green -->
<place id="green" x="64" y="64" depth="0"/>
</frame>
When you're placing more than one clips to a frame, it is safest to do so in a separate clip. This way you can still overwrite the whole frame by simply placing a new clip in its place.
<frame>
<!-- Create a sub clip -->
<clip id="redGreen">
<frame>
<place id="red" x="0" y="0" depth="0"/>
<place id="green" x="64" y="64" depth="1"/>
</frame>
</clip>
<!-- A clip containing both red and green at zero depth -->
<place id="redGreen" x="0" y="0" depth="0"/>
</frame>
<frame>
<!-- Overwrite redGreen with plain red -->
<place id="red" x="64" y="64" depth="0"/>
</frame>
Swfmill can be used to create Shared Libraries for Dynamic Font Loading at runtime, a nice hack described by Erixtekila. This is well documented with examples by Mike Barbero .
Essentially, you have to load an SWF (containing the font) which loads itself as a shared library. Here's an example, shamelessly ripped from Mike's page:
<?xml version="1.0" encoding="iso-8859-1" ?>
<movie width="1" height="1" framerate="12">
<frame>
<library>
<font name="Charter" import="src/ct.ttf"/>
<font name="Charter" import="src/ct__Italic.ttf"/>
<font name="Charter" import="src/ct__Bold.ttf"/>
<font name="Charter" import="src/ct__BoldItalic.ttf"/>
</library>
<Import url="http://localhost/test/charters.swf"></Import>
</frame>
</movie>
As you can see in the <import/>
tag for the
dynamic library, the URL for the SWF must be
http://localhost/test/charters.swf
.
Relative paths work, too. So, when you need to load the font, you
load the SWF you generated and it will load itself out of
the browser cache.
The @name
is set to the same value in all
<font/>
tags on purpose, so you can use
e.g., <b/>
in HTML TextFields. Of course it
also works with just a single style, with only a selected subset
of the glyphs, and so on.
Earlier in this document a method for importing components was provided. This method allows you to add the components directly into the SWFs using only swfmill, but can potentially cause much larger output files. If you have access to the Flash IDE there is another simple method to add components.
Basically, you will use the Flash IDE to generate a blank SWF which contains the components you will want to use. Then, in your XML you add a clip to the library that imports this SWF. It appears that simply importing the clip has the effect of adding the components to the library, without even having to instantiate the clip.
For example, if you create an SWF using the Flash IDE which simply
contains the ComboBox component and build it as
Components.swf
you can then do this in the XML:
<frame>
<library>
<clip id="componentsContainer" import="Components.swf"/>
</library>
</frame>
then in your code wherever you wish to create the combo box you simply import the control's class at the top:
import mx.controls.ComboBox
and then instantiate it with the following (replacing
_root
with the movie clip you want to attach to
and myComboBox
with the name you wish to give it):
_root.createClassObject(ComboBox, "myComboBox" _root.getNextHighestDepth());
var cb:ComboBox = _root["myComboBox"];
SVG support works great for files produced by Inkscape.
All groups (svg:g
) in SVG are exported as movie clips
(for Inkscape this affects layers as well as groups). These movie
clips are named after either their inkscape:label
attribute if that exists (first character '#' removed if present)
or id
attribute (inkscape:label
is better
because it allows reusing name in different point of hierarchy. If
group has transform
attribute, all it's contents are
created in yet another movie clip (usually called
instance
N) with appropriate transformations
applied.
If some element has swfClass
attribute, then specified
class is assigned to a movieclip corresponding to that element. All
prerequisites described
above must also be
satisfied here.
A few more words about Inkscape. To set label you can right-click
any object and choose Object Properties. To set class you
can select object, pop up an XML Editor (e.g. using
Ctrl+Shift+X
) and enter swfClass
and
appropriate value, then click set.
Fame + Swfmill = Fully open source flash Post/tutorial on using Swfmill with FAME .