The player keeps a display list: the objects on the stage, each at a depth, a UI16, with higher depths drawn on top. A depth holds one object. Each frame’s control tags change the list, by placing, changing and removing objects, and a ShowFrame tag draws it. A sprite has a display list and timeline of its own.
ShowFrame (1)
No body. Draws the display list as the tags before it have left it, and starts the next frame. The main timeline’s frame count in the header is the number of ShowFrame tags in its run.
PlaceObject (4)
| Offset | Size | Type | Name | Meaning |
|---|---|---|---|---|
| 0 | 2 | UI16 | CharacterId | The character to place |
| 2 | 2 | UI16 | Depth | Where to place it |
| 4 | varies | MATRIX | Matrix | Its position, scale and rotation |
| … | varies | CXFORM | ColorTransform | Only if bytes remain in the tag |
Puts a new object at the depth. 08 01 02 00 01 00 18 FA 04 B0 places
character 2 at depth 1, 100 pixels right and 30 down.
RemoveObject (5)
| Offset | Size | Type | Name | Meaning |
|---|---|---|---|---|
| 0 | 2 | UI16 | CharacterId | The character to remove |
| 2 | 2 | UI16 | Depth | Its depth |
PlaceObject2 (26, SWF 3)
Places a new object or changes the one at a depth. A flags byte says which fields follow. Read most significant bit first:
| Bit | Value | Name | Meaning |
|---|---|---|---|
| 7 | 0x80 | PlaceFlagHasClipActions | Clip actions follow (SWF 5) |
| 6 | 0x40 | PlaceFlagHasClipDepth | A clip depth follows |
| 5 | 0x20 | PlaceFlagHasName | An instance name follows |
| 4 | 0x10 | PlaceFlagHasRatio | A ratio follows |
| 3 | 0x08 | PlaceFlagHasColorTransform | A colour transform follows |
| 2 | 0x04 | PlaceFlagHasMatrix | A matrix follows |
| 1 | 0x02 | PlaceFlagHasCharacter | A character ID follows |
| 0 | 0x01 | PlaceFlagMove | Change the object already at the depth |
Then, in this order, each only when flagged except the depth:
| Type | Name | Meaning |
|---|---|---|
| UI16 | Depth | Always present |
| UI16 | CharacterId | The character to place |
| MATRIX | Matrix | Position, scale and rotation |
| CXFORMWITHALPHA | ColorTransform | Colour and alpha transform |
| UI16 | Ratio | For a morph shape, the morph position, 0 to 65,535; for a video, the frame |
| STRING | Name | The instance name, used by ActionScript |
| UI16 | ClipDepth | This object is a mask for every depth above it up to ClipDepth |
| CLIPACTIONS | ClipActions | Event handlers |
Move and HasCharacter together decide what happens:
- Move 0, with a character: place a new object; the depth should be empty.
- Move 1, no character: change the object at the depth, only the fields given.
- Move 1, with a character: replace the object’s character, keeping its other properties unless they are given.
PlaceObject3 (70, SWF 8)
PlaceObject2’s flags byte, then a second flags byte, read most significant bit first:
| Bit | Value | Name | Meaning |
|---|---|---|---|
| 7 | 0x80 | Reserved | 0 |
| 6 | 0x40 | PlaceFlagOpaqueBackground | A background colour follows |
| 5 | 0x20 | PlaceFlagHasVisible | A visibility byte follows |
| 4 | 0x10 | PlaceFlagHasImage | The class name is of a bitmap |
| 3 | 0x08 | PlaceFlagHasClassName | A class name follows |
| 2 | 0x04 | PlaceFlagHasCacheAsBitmap | A bitmap cache byte follows |
| 1 | 0x02 | PlaceFlagHasBlendMode | A blend mode follows |
| 0 | 0x01 | PlaceFlagHasFilterList | A filter list follows |
The SWF 10 specification had three reserved bits where SWF 19 has Reserved, OpaqueBackground and HasVisible, which arrived with Flash Player 11. The fields follow in this order:
| Type | Name | When |
|---|---|---|
| UI16 | Depth | Always |
| STRING | ClassName | HasClassName, or HasImage and HasCharacter: the ActionScript 3 class to make an instance of |
| UI16 | CharacterId | HasCharacter |
| MATRIX | Matrix | HasMatrix |
| CXFORMWITHALPHA | ColorTransform | HasColorTransform |
| UI16 | Ratio | HasRatio |
| STRING | Name | HasName |
| UI16 | ClipDepth | HasClipDepth |
| FILTERLIST | SurfaceFilterList | HasFilterList |
| UI8 | BlendMode | HasBlendMode; see blend modes |
| UI8 | BitmapCache | HasCacheAsBitmap; 0 off |
| UI8 | Visible | HasVisible; 0 hidden |
| RGBA | BackgroundColor | OpaqueBackground |
| CLIPACTIONS | ClipActions | HasClipActions |
RemoveObject2 (28, SWF 3)
| Offset | Size | Type | Name | Meaning |
|---|---|---|---|---|
| 0 | 2 | UI16 | Depth | Removes whatever is at this depth |
FrameLabel (43, SWF 3)
| Offset | Size | Type | Name | Meaning |
|---|---|---|---|---|
| 0 | varies | STRING | Name | The label of the current frame |
| … | 1 | UI8 | NamedAnchorFlag | Optional: 1 if the label is also a named anchor |
A named anchor is a frame the browser’s Back and Forward buttons can reach. Actions go to a label with ActionGoToLabel.
DefineSprite (39, SWF 3)
| Offset | Size | Type | Name | Meaning |
|---|---|---|---|---|
| 0 | 2 | UI16 | SpriteID | The character ID |
| 2 | 2 | UI16 | FrameCount | The frames in the sprite |
| 4 | varies | tags | ControlTags | A tag run of its own, ending with End |
A sprite is a movie clip: it plays its own timeline wherever it is placed. Its tags are walked like the movie’s; see the tag run for which tags may appear inside.
Clip actions
A PlaceObject2 or PlaceObject3 with HasClipActions ends with event handlers for the
placed movie clip: what onClipEvent (…) and on (…) on an
instance compile to. The flags are 32 bits in this format.
| Type | Name | Meaning |
|---|---|---|
| UI16 | Reserved | 0 |
| CLIPEVENTFLAGS | AllEventFlags | Every event any handler below uses |
| CLIPACTIONRECORD[] | ClipActionRecords | One per handler |
| UI32 | ClipActionEndFlag | 0: the end of the list |
Each CLIPACTIONRECORD:
| Type | Name | Meaning |
|---|---|---|
| CLIPEVENTFLAGS | EventFlags | The events this handler runs on |
| UI32 | ActionRecordSize | The bytes after this field in the record |
| UI8 | KeyCode | Only if EventFlags has ClipEventKeyPress: the key, as in button key codes |
| ACTIONRECORD[] | Actions | Actions ending with an End action (0) |
CLIPEVENTFLAGS
Four bytes, read as bits most significant first, byte by byte:
| Byte | Bits, from the top |
|---|---|
| 1 | KeyUp, KeyDown, MouseUp, MouseDown, MouseMove, Unload, EnterFrame, Load |
| 2 | DragOver, RollOut, RollOver, ReleaseOutside, Release, Press, Initialize, Data |
| 3 | 5 reserved bits, Construct (SWF 7), KeyPress, DragOut |
| 4 | 8 reserved bits |
Read as a little-endian UI32 instead, the values are: Load 0x01, EnterFrame 0x02, Unload 0x04, MouseMove 0x08, MouseDown 0x10, MouseUp 0x20, KeyDown 0x40, KeyUp 0x80, Data 0x100, Initialize 0x200, Press 0x400, Release 0x800, ReleaseOutside 0x1000, RollOver 0x2000, RollOut 0x4000, DragOver 0x8000, DragOut 0x10000, KeyPress 0x20000, Construct 0x40000. Initialize, the button-like events and KeyPress arrived with SWF 6.
A real example
From a SWF 6 movie: a PlaceObject2 placing character 3 at depth 1 with two
handlers, onClipEvent (initialize) and
onClipEvent (enterFrame).
000002B2 BF 06 EC 00 00 00 86 01 00 03 00 18 FA 04 B0 00
000002C2 00 02 02 00 00 00 02 00 00 27 00 00 00 96 0E 00
86: clip actions, matrix, character. Then depth 1,
character 3, the matrix, Reserved 00 00, AllEventFlags
02 02 00 00 (EnterFrame and Initialize); the first record’s
EventFlags 00 02 00 00 (Initialize) and ActionRecordSize 39, then its
actionsFilters (SWF 8)
A FILTERLIST is a UI8 NumberOfFilters, then that many filters, each a UI8 FilterID and its data. The explorer reads the list but does not draw filters.
| ID | Filter | Bytes | Fields |
|---|---|---|---|
| 0 | DropShadow | 23 | RGBA DropShadowColor, FIXED BlurX, FIXED BlurY, FIXED Angle (radians), FIXED Distance, FIXED8 Strength, UB[1] InnerShadow, UB[1] Knockout, UB[1] CompositeSource (always 1), UB[5] Passes |
| 1 | Blur | 9 | FIXED BlurX, FIXED BlurY, UB[5] Passes, UB[3] Reserved |
| 2 | Glow | 15 | RGBA GlowColor, FIXED BlurX, FIXED BlurY, FIXED8 Strength, UB[1] InnerGlow, UB[1] Knockout, UB[1] CompositeSource, UB[5] Passes |
| 3 | Bevel | 27 | RGBA ShadowColor, RGBA HighlightColor, FIXED BlurX, FIXED BlurY, FIXED Angle, FIXED Distance, FIXED8 Strength, UB[1] InnerShadow, UB[1] Knockout, UB[1] CompositeSource, UB[1] OnTop, UB[4] Passes |
| 4 | GradientGlow | 20 + 5n | UI8 NumColors, RGBA × n, UI8 ratio × n, FIXED BlurX, FIXED BlurY, FIXED Angle, FIXED Distance, FIXED8 Strength, UB[1] InnerShadow, UB[1] Knockout, UB[1] CompositeSource, UB[1] OnTop, UB[4] Passes |
| 5 | Convolution | 15 + 4xy | UI8 MatrixX, UI8 MatrixY, FLOAT Divisor, FLOAT Bias, FLOAT × (MatrixX × MatrixY), RGBA DefaultColor, UB[6] Reserved, UB[1] Clamp, UB[1] PreserveAlpha |
| 6 | ColorMatrix | 80 | FLOAT × 20: a 4 × 5 matrix, row by row |
| 7 | GradientBevel | 20 + 5n | As GradientGlow |
The byte counts include the FilterID. Any other ID is not defined, and the list cannot be read past it.
Blend modes (SWF 8)
| Value | Mode | Value | Mode |
|---|---|---|---|
| 0, 1 | Normal | 8 | Add |
| 2 | Layer | 9 | Subtract |
| 3 | Multiply | 10 | Invert |
| 4 | Screen | 11 | Alpha |
| 5 | Lighten | 12 | Erase |
| 6 | Darken | 13 | Overlay |
| 7 | Difference | 14 | Hard light |
DefineScalingGrid (78, SWF 8)
| Offset | Size | Type | Name | Meaning |
|---|---|---|---|---|
| 0 | 2 | UI16 | CharacterId | A sprite or button |
| 2 | varies | RECT | Splitter | The centre of the 9-slice grid |
When the character is scaled, the corners outside the rectangle keep their size, the edges stretch one way and the centre both ways.
DefineSceneAndFrameLabelData (86, SWF 9)
| Type | Name | Meaning |
|---|---|---|
| EncodedU32 | SceneCount | The number of scenes |
| EncodedU32, STRING | FrameOffset, Name | Each scene: its first frame and its name |
| EncodedU32 | FrameLabelCount | The number of labels |
| EncodedU32, STRING | FrameNum, FrameLabel | Each label: its frame and its text |
Frame numbers count from 0. It gives ActionScript 3 the main timeline’s scenes and labels.
How the explorer draws a frame
The explorer replays the control tags up to the frame and draws the display list: shapes, morph shapes at the placed ratio, sprites at the frame they reach (stopping where a frame’s actions hold ActionStop), buttons in their up state, static text and text fields drawn with their embedded outlines, with matrices, colour transforms and clip-depth masks. It does not run ActionScript, so anything a script creates or moves is missing, and it does not draw filters, blend modes or video.