swfmill
- Homepage: http://swfmill.org/
- Subversion: http://swfmill.org/svn/trunk via Trac
- Mailing List: http://osflash.org/mailman/listinfo/swfmill_osflash.org
- License: GNU GPL
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?
Anything else?
swfmill was written by Daniel Fischer and is published under the GPL.
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 &, > <, ", 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" />
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.
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.
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, here.
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. There are a couple of bugs supporting other svg files (e.g. #12). Currently you can only import single SVG file into SWF (#14, seems to be fixed in trunk).
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.
Relevant Links
- Fame + Swfmill = Fully open source flash (FlashAnt post/tutorial on using Swfmill with FAME).
swfmill.txt · Last modified: 2010/01/14 10:43 by aral