This page contains some documentation that was previously hosted on the now defunct OSFlash wiki. It is rather old, disorganised and unhelpful. Sorry :(.

Table of Contents

swfmill

Overview

What is it?

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.

What can I do with the xslt processor?

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.

For which platforms is it available?

You can download windows and OS X and the sources for Linux. 64 bit processors are supported since version 0.2.3.

Where can I find more information?

Please follow the links at the bottom of this page for some examples and documentation, and visit the homepage.

Is there a mailing list where I can get help?

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.

Anything else?

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.

Examples for the “simple” vocabulary

The most basic SWF

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

Importing Assets

Importing Images and SWFs

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>

A simple Library

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>

Importing Fonts

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.

Font Rendering Engine

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.

Font Name Conflicts

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.

Special Characters and the glyphs Attribute

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 &amp;, &gt; &lt;, &quot;, and &apos;. 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="&#x00A1&amp;&gt;A" />
id versus name

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.

Importing a Sound

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.

Importing a Shared Library

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"/>

Assigning a Class to a MovieClip

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>

Using components

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

Publishing to Flash 8

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.

Flash 8 new features

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.

Publishing AS3 compatible files

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">

Advanced

Multi-state MovieClips

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.

Compositing frames with place

'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>

Dynamic Shared Font Loading

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.

Alternate Component Import Method

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 features and issues

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 instanceN) 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.