Most of the tags will use sub-structures that are common to multiple tags. These are defined in the pages listed below.
The color components can be set to any value from 0 (no intensity) to maximum intensity (255).1
It is important to note that even fully transparent pixels may not have their red, green, blue components set to 0. This is useful if you want to add a value to the alpha channel using one of the color transformation matrices. In that case, using all 0's would generate a black color.
f_red = orginal red * f_alpha / 255
This format was added to be mostly compatible with the old PNG format (XRGB).
An action is defined with an identifier, and an optional size and data (pretty much like a tag).
Note that the optional size and data are defined only for actions with an identifier of 128 or more. The other identifiers are always defined by themselves. Actions without immediate data may still access data. In that case, the data is taken from the stack.
Please, see the action list for all the supported actions.
Since Flash version 9, actions can be saved in a new format named abcFormat by the Tamarin project from the Mozilla organization.
The code itself (action script) is the same, but the structure of an swf_action3 holds object oriented information about classes, methods and such in a really clean way (really! in comparison to the old way, that's dead clean!).
At this time, the swf_action3 structure is documented in the abcFormat.html file.
I will duplicate and test the structures at a later time.
A filter defines how to transform the objects it is attached to. The first byte is the filter type. The data following depend on the type. Because each filter is much different, they are defined in separate structures. You can attach a filter to an object using an ActionScript or the PlaceObject3 tag.
The following describes the different filters available since version 8.
Value Name Version 0 Drop Shadow 8 1 Blur 8 2 Glow 8 3 Bevel 8 4 Gradient Glow 8 5 Convolution 8 6 Color Matrix 8 7 Gradient Bevel 8
Glow, Drop Shadow, Bevel, Gradient Glow and Gradient Bevel
The following structure describes the Glow, Drop Shadow, Bevel, Gradient Glow and Gradient Bevel which all use the same algorithm. Those with less parameters can use a faster (optimized) version of the full version algorithm.
These filters are used to generate what looks like a glow or a shadow. It uses the alpha channel of the object being filtered. Only the alpha is used in the computation of the shape until the end when the color is applied. The result is then composited with the object (unless f_knock_out is set to 1 in which case it replaces the object) before being drawn in the display.
The f_count is assumed to be 1 unless a gradient filter is used, in which case a byte will be defined here. Note: the maximum number of gradient is not specified in the Macromedia documentation. It can be assumed to be the same as for the other gradients and thus it either can be 1 to 8 or 1 to 15. I will need to test that too!
The f_rgba color is used as the final step to color the resulting shape. A standard shadow uses a black or dark gray color and a standard glow has a color between the general color of the object being filtered and white.
The f_hightlight_rgba color is used by the Bevel filter to color the second half of the final shape (f_rgba colors the first half). This is usually set to a glow color whereas the f_rgba is set to a shadow color.
The f_position is used as the position of that specific gradient entry. This is similar to the f_position parameter of the swf_gradient_record.
The f_blur_horizontal and f_blur_vertical values are used to blur the edges horizontally and vertically. See the Blur filter for more information about the blur effect.
The f_radian_angle and f_distance are used to move the shadow away from the object being placed. Notice that the angle is in radian. Increasing the angle turns the effect clockwise. An angle of 0.0 points to the right side of the object.
The f_strengh value is used to multiply the resulting grey scale. Smaller values make the shadow darker. 1.0 keeps the alpha channel as it is (beside the blur).
The f_inner_shadow flag means that the result is applied inside the parent object and not arround as you would expected for a shadow. If you need both: an inner and an outer shadow (necessary for semi-transparent objects) then you will need to setup two filters.
The f_knock_out flag means that the source object is not rendered in the result, only the shadow. This can be used (in general) to draw the edges of the object. It can also be used to apply a different transformation on the shadow than on the object (in which case the object will be twice in the display list: once to draw its shadow and once to draw itself.)
The f_composite_source must be set to 1 for the Drop Shadow.
The f_on_top flag indicates whether the resulting shadow and highlight should be rendered below (0) or over (1) the source image. This is at times referenced as Overlay.
The f_passes counter available with the gradient filters can be used to repeat the filter computations multiple times. This parameter should be set to 1, 2 or 3. A value of 0 is illegal and a larger value will not only slow down the computation time, it is likely to generate a bad result.
The Blur filter applies a seemingly complex mathematical equation to all the pixels in order to generate soft edges. To simplify: it adds the surrounding pixels to a center pixel and normalize the result. This generates the effect of a blurry image. Note that this blur is applied to squares (box filter).
The math in a C++ function goes like this:
swf_rgba blur(const char *image, int x, int y, int blur_h, int blur_v) { /* we assume that blur_h/v are odd */ int x1 = x - blur_h / 2; int x2 = x + blur_h / 2; int y1 = y - blur_v / 2; int y2 = y + blur_v / 2; swf_rgba blur; blur.reset(); /* set to all 0's */ yp = y1; while(yp <= y2) { int xp = x1; while(xp <= x2) { blur += image(xp, yp); ++xp; } ++yp; } return blur / (blur_h * blur_v); }
Notes: | The Flash player implementation works on sub-pixels and this algorithm does not. |
The fact that this algorithm uses a square means it will generate visible artifacts in your image if you use a large value for the blur (i.e. more than about 7.) | |
If you want this algorithm to work properly, make sure to save the results in a separate image so each pixel can be computed properly without the effect pre-applied. | |
This algorithm does not show any clipping; if you want to keep it fast, you need to keep it that way and enlarge the source image making the edges a repeat of the edge color and the corners the corresponding corner color. |
The f_blur_horizontal and f_blur_vertical are expected to be larger than 1.0 to have an effect (usually at least 3, and in most cases 5 or more.)
The f_passes is a counter which should be at least 1. The blur effect will be repeated that many times on the image. When using 3, the resulting blur is close to a Gaussian Blur. Note that it will make the image bigger each time and applying this filter can be slow.
The convolution filter can be used to generate a really nice blur or avoid the vertical jitter of an animation on a CRT monitor. It is similar to the Blur filter, except that the computation of the destination pixels is fully controlled.
Fig 1 — Convolution Filter Example
The image above shows an example of a convolution filter. The red pixel is the one being tweaked. The different gray color represent the heavier (darker) weight and the lighter weights. The pixels drawn in white are ignored (i.e. their weights will be set to 0.)
The convolution filter can be described with the following C function:
swf_rgba convolution(swf_rgba *source, int x, int y, swf_filter_convolution convolution) { swf_rgba result; swf_rgba pixel; int i, j, p, q, pmax, qmax; result.reset(); /* black */ pmax = convolution.f_rows / 2; qmax = convolution.f_columns / 2; for(j = 0, p = -pmax; p < pmax; ++p, ++j) { for(i = 0, q = -qmax; q < qmax; ++q, ++i) { pixel = source[x + p][y + q]; pixel += convolution.f_bias; pixel *= convolution.f_weights[i][j]; pixel /= convolution.f_divisor; result += pixel; } } return result; }
We can clearly see that a weight of 0 cancels that very pixel effect. We can notice also that the divisor is not necessary here (however, it may be possible to tweak the divisor using an ActionScript and in that case it can be useful.)
A blur algorithm can use a convolution filter with the following parameters:
{ { 0.000, 0.050, 0.050, 0.050, 0.000 }, { 0.050, 0.075, 0.075, 0.075, 0.050 }, { 0.050, 0.075, 0.000, 0.075, 0.050 }, { 0.050, 0.075, 0.075, 0.075, 0.050 }, { 0.000, 0.050, 0.050, 0.050, 0.000 } }
Fig 2 — Convolution filter to create a radian blur
When you want to remove most of the jitter on a television or any CRT monitor which use an interlace video mode, you can use the following setup:
Fig 3 — Convolution filter to limit interlace jitter
The f_columns and f_rows determine the size of the convolution filter.
The f_divisor divide the sum of the weighted pixel components. Note that you can incorporate the divisor in the weights. However, this is a mean to divide (or multiply) all the weights at once. Yet I suggest you put this parameter to 1 and change the weights instead.
The f_bias is added to the component of each pixel before they are multiplied by their corresponding factor.
The f_weights are used to determine how much of a given pixel color shall be used in the result.
The f_default_color color is used only if f_clamp is set to 0. This is the color to be used whenever it is necessary to compute the color of a pixel which is outside of the source.
f_clamp is used to determine the color to use whenever a pixel outside of the input image is necessary. When set to 1, the closest input pixel is used. When set to 0, the f_default_color is used.
If f_preserve_alpha is set to 1, then the source alpha channel is copied as is in the destination.
The color matrix is a 5x5 matrix used to tweak or adjust the colors of your objects. A full matrix can be used to change the contrast, brightness and color (just like you do on your television.)
The matrix is composed of 5 components of red, green, blue and alpha. The 5th row is not saved in the filter and is assume to always be [0 0 0 0 1].
Fig 1 — Color Matrix Filter
The resulting color Q is computed as M · C, where C is a column matrix composed of the source pixel colors: red, green, blue, alpha and 1. The result is also a column matrix in which component 5 can be dropped.
Notice that f_matrix is composed of floats and not fixed point values.
In order to compute a color matrix from simple values, you want to use the following matrices and equations (see Appendix A. for more matrix computations.) Most of these equations are based on a paper written by Paul Haeberli in 1993.
Why is matrix computation on colors working so well? This is because the colors, when defined as (R, G, B) perfectly map to a 3 dimensional cube. The corner at (0, 0, 0) represents black, and the opposite corner at (1, 1, 1) represents white. The other corners represent Red, Green, Blue and their composites: Cyan, Yellow, Purple. Within the cube, all the usual 3D geometry computations apply to colors just the same as it applies to (x, y, z) vectors.
The following shows you have to modify the RGB components. The Alpha channel can in a similar way be modified. However, you usually do not want to change the alpha from the colors and thus it is likely that the only thing you will do with the alpha is a simple translation (change a0, a1, a2) and a scaling (change a3). By default, set the alpha row to [ 0 0 0 1 0 ] and the last column to [ 0 0 0 0 1 ].
Fig 2 — Color Matrix with no effect on the alpha channel
In the following pretty much all the values are assumed to be defined between 0.0 and 1.0. Though there is no real limits, using larger values or negative values can have unexpected effects such as a clamping of one or more of the color components.
The Grey Vector is the vector going from (0, 0, 0) to (1, 1, 1). It represents all the grays from black to white. It is important since it is used to represent the luminance of the image.
Use the scaling matrix B to change the brightness. This has the effect of making the color vector longer or shorter, but it still points in the same direction. Some people call this the image Intensity.
Fig 3 — Brightness Matrix B
In general, you want to set all scaling factors to the same value to change the brightness in a uniform way. By changing the scaling factors to different values you in effect change the color balance.
The luminance matrix L is used to determine how close your image is to the grey vector. The closer to the gray vector, the closer to a black and white image you will get. This is a saturation toward grey. The effect in the color cube is to move your color vector closer to the grey vector.
Fig 4 — Luminance Matrix (L)
The luminance matrix requires three weights (Rw, Gw, Bw) which are defined as (0.3086, 0.6094, 0.082). Note that the sum of these weights is 1.0.
The weights used here are linear. It is possible to use different weights for images which have different gammas. For instance, an NTSC image with a gamma of 2.2 has these weights: (0.299, 0.587, 0.114).
The saturation matrix S is used to saturate the colors. This matrix uses the weights defined for the Luminance matrix L. The effect in the color cube is to move your vector toward another vector. The Luminance is a special case which moves your vector toward the gray vector. And the identity matrix, which can also be considered a saturation matrix, is a special case which does not move your vector.
Fig 5 — Saturation Matrix (S)
The saturation parameter s shall be set to a value from -1 to 1. Note that a saturation of 1 generates an Identity Matrix and thus has no effect. A saturation of 0 generates a Luminance Matrix (s = 0 <=> S = L). A saturation of -1 generates a matrix which inverse all the colors of your image (negative).
Using the Brightness Matrix B and a translation matrix, it is possible to modify the contrast of your image by scaling the colors toward or away from the center (or some other point) of the color cube.
Fig 6 — Translation Matrix (T)
To apply a standard contrast c create a matrix Ts with offsets (0.5, 0.5, 0.5), a matrix Bc with the scaling factors set to c and compute the contrast matrix C as: C = -Ts · Bc · Ts
It is also possible to use a translation to change the colors of your image. This is not very useful since it is a simple addition (C' = C + T).
To change the hue of a color, it is necessary to rotate the color vector around the gray vector. It is easy to see that rotating the gray vector around itself generates itself. A gray hue cannot be changed. If you rotate the colors by 120°, red becomes green, green becomes blue and blue becomes red.
Note however that by only rotating the color, you generate a luminance error. This is because blue is not as bright as red or green and green is not as bright as red. To avoid the luminance loss, you need to apply a shear to make the luminance plane horizontal.
The following are all the steps used to rotate the Hue. Note that most matrices can be precomputed (in other words, you can very much optimize your code!)
Once you computed each of the matrices, you can merge them all together by multiplying them. The order should not matter except if you use a translation which isn't canceled (like the one for the contrast.)
M = B · S · C · H
Note that you do not need a Saturation and a Luminance since these are the same. However, you may still want to separate them for the sake of simplicity.
M = B · L · S · C · H
Rotate the gray vector around the X axis by 45°. This places the the vector on the (x, y) plane.
Fig 7 — rotation around the X axis
Because we want to rotate by 45° the sine and cosine of the angle can directly be set to the inverse of the square root of 2.
Fig 8 — sine and cosine in the rotation around the X axis
Rotate the gray vector from the (x, y) plane to the positive Z direction. We want to rotate by about 35.2644°.
Fig 9 — rotation around the Y axis
The sine and cosine values of this equation can be computed with the square root of 2 and 3 as presented below:
Fig 10 — sine and cosine in the rotation around the Y axis
Apply the Rx and Ry matrices to the luminance offsets, and use the result to compute the shear matrix.
Fig 11 — How to compute the shear factors
The Rw, Gw and Bw are the Luminance factors as defined for matrix L.
Now we can compute matrix K which is used for the luminance shear correction:
Fig 12 — Hue Shear Matrix K
Once you applied the Rx, Ry and K matrices to your color, you can safely rotate the result around the Z axis. This rotates the hue of the color. The rotation angle is expected to go from 0 to 2π.
Fig 13 — Matrix to rotate the hue
θ is set to the hue rotation angle.
Once you rotated your vector using Rz you need to put your vector back where it belongs. This is done by multiplying by the inverse of the K, Ry and Rx in that order. Note that since these matrices are quite simple, calculating their inverse is very easy.
K-1 is obtained by replacing B'w in the K matrix by –B'w.
Fig 14 — Inverse of Matrix K
Ry-1 and Rx-1 are obtained by replacing the sine values by their opposite.
Fig 15 — Inverse of Matrix Ry
Fig 16 — Inverse of Matrix Rx
Given the hue rotation angle θ you can write:
H = Rx · Ry · K · Rz · K-1 · Rx-1 · Ry-1
Filters Union
The any filter is simply a union of all the filters. Note that only one type of filter can be defined in an any filter and also the size will depend on that filter (it is not the largest size of all filters; plus, some filters use a dynamically determined size!)
A button structure defines a state and a corresponding shape reference. The shape will be affected by the specified matrix whenever used.
There are many acceptable combinations. The object which is referenced is drawn when its state matches the current state of the button. If only the f_button_state_hit_test is set, then the shape is always displayed.
In order to define the area where the button can be clicked, it is necessary to set the f_button_state_hit_test flag to 1. Also, when this flag is set, only a shape can be referenced (no edit text, sprite or text object will work in this case).
When the f_button_state_hit_test is set, the square used to delimit the referenced shape will be used to determine whether the mouse is over the button or not.
Shapes referenced with the f_button_state_down flag set are drawn when a mouse button is being pushed over this button.
Shapes referenced with the f_button_state_up flag set are drawn when no mouse button is being pushed over this button. When neither up or down is specified, up us assumed.
Shapes referenced with the f_button_state_over flag set are drawn when the mouse is moved over this button.
The f_button_layer is used like a depth parameter. The smallest layer is drawn first (behind) and the highest layer is drawn last (on top of all the other shapes).
Though four flags allow for 16 different states, you are likely to only use a few. The hit test can appear on each state. The down and up won't usually be used together, though, if they are the shape will be drawn when the button is clicked or not.
Since version 8, this structure supports blending modes and a list of filters.
The structure is always aligned to a byte. If all of the f_button_state_... flags are zeroes, then the entry is an EOB (End Of Buttons) entry.
When the f_color_<component>_mult are not defined in the input file, use 1.0 by default. When the f_color_<component>_add are not defined in the input file, use 0.0 by default.
The factors are saved as 8.8 fixed values (divide by 256 to obtain a proper floating point value). Note that the values are limited to a signed 16 bits value. This allows for any value between -128.0 and +127.98828.
When the resulting color is defined, the multiplication is applied first as in:
result-component = source-component * component-mult + component-add;
The result is then clamped between 0.0 and 1.0.
A condition is defined in a DefineButton2 tag. It is a record of conditions. The record terminates when the size of the current (i.e. last) condition is zero. The length of that condition can be deduced from the total size of the tag minus the offset where the condition starts. Conditions are similar to events.
The f_key field represents a key code since version 4. The following table gives the code equivalence. Note that 0 means no key.
Key Code | Name | Version |
---|---|---|
0 (0x00) | No key activation | 3 |
1 (0x01) | Left Arrow | 4 |
2 (0x02) | Right Arrow | 4 |
3 (0x03) | Home | 4 |
4 (0x04) | End | 4 |
5 (0x05) | Insert | 4 |
6 (0x06) | Delete | 4 |
8 (0x08) | Backspace | 4 |
13 (0x0D) | Enter | 4 |
14 (0x0E) | Up Arrow | 4 |
15 (0x0F) | Down Arrow | 4 |
16 (0x10) | Page Up | 4 |
17 (0x11) | Page Down | 4 |
18 (0x12) | Tab | 4 |
19 (0x13) | Escape | 4 |
32-126 | The corresponding ASCII code | 4 |
When playing back a sound effect it is possible to modulate the sound to generate different effects (such as a fade in and out). The following defines the stereo volume of the sound.
The position is always given as if the sample data was defined with a rate of 44,100 bytes per seconds. For instance, the sample number 1 in a sound effect with a sample rate of 5.5K is given as position 8 in the envelope. All of these positions should be within the f_in_point and f_out_point.
Mono sound should use the same value for the left and right volumes. Note that it will automatically be averaged if necessary.
Note that the volume goes from 0 to 32768.
An event is defined in a PlaceObject2 tag. It is a record of events terminated with a set of zero flags. Events are similar to conditions.
An external reference is a per of entries: an identifier and a name. The name is called the external symbol and is used to match the necessary definitions between two movies using Export, Import and Import2
The fill style is defined in the first byte. The values are defined below. Depending on that value, the fill style structure changes as shown below. swf_fill_style is a union of all the other structures.
Notice that types 0x42 and 0x43 are only available since version 7 and type 0x13 is only available since version 8.
Note that these values were introduced in Flash 7 but it looks like only player 8 supported the distinction between hard edges and smooth edges on a per shape basis. That would explain why I could not see any difference between smooth and hard shapes when I tested this feature in Flash 7.
Before Flash 8, all shapes would be smoothed if the global quality of the movie was set to BEST. In Flash 8, nothing is smoothed by default whatever the quality and the smoothed or hard selection in a shape can be used as a hint on a per shape basis. Following this specification closely can be important in some situations.
The array of fill styles starts with a counter. When DefineShape is used, the counter can be any value from 0 (no style) to 255. When DefineShape2 or DefineShape3 are used, the value 255 is reserved so you can declare more than 255 styles.
This structure defines a gradient. This is a set of colors which are used to define an image with colors smoothly varying from one color to the next. The gradient can be radial (circular) or linear (rectangular).
The f_count
field is limited depending on the tag used and the version of SWF as defined below:
Range Tag Version 1 to 8 DefineShape 3 1 to 8 DefineShape2 3 1 to 8 DefineShape3 3 1 to 15 DefineShape4 8 1 to 8 DefineShapeMorph 3 1 to 8(1) DefineShapeMorph2 8
(1) To be determined. The Macromedia documentation says it is limited to 8, the player needs to be tested to verify that DefineShapeMorph2 cannot support 15 gradients
The f_spread_mode
is an enumeration and appeared in version 8 (undefined values are reserved.)
Value Comment Version 0 Pad 8 1 Reflect 8 2 Repeat 8
The f_interpolation_mode
is an enumeration and appeared in version 8 (undefined values are reserved.)
Value Comment Version 0 Normal RGB mode 8 1 Linear RGB mode 8
The f_focal_point
is a position from the left edge of the gradient square to the center and then to the right edge of the gradient. The left edge is at position -1.0, the center at 0.0 and the right edge at +1.0. This is particularly useful for radial gradients.
The first record position should be 0 and the last 255. The intermediate should use the corresponding value depending on their position in the gradient effect.
A linear gradient is defined from left to right. A radial from inside to outside. In order to see the full effect of the gradient, one needs to define its matrix properly. The gradients are always drawn in a square with coordinates -819.2, -819.2 to +819.2, +819.2 (in pixels, that's 16384 in TWIPs). The usual is to scale the gradient square down, translate to the proper position and rotate as necessary. There is no point in rotating a radial gradient.
IMPORTANT NOTE: If you use positions (see f_position) which are too close to each others, you are likely to see a reverse effect of what you would expect (Well... at least in the Macromedia plugin V5.0 — the gradient goes the wrong way between each color change!!!).
Fig 1. Red to green radial fill
The image in Fig 1. shows you a radial fill using pure red as the color at position 0 and pure green at position 255. It is often used to draw a round corner of an object such as a button.
Fig 2. Red to green linear fill
The image in Fig 2. shows you a linear fill using pure red as the color at position 0 and pure green at position 255. It goes from left to right when no rotation is applied. Using a rotation provides means to have the colors going top to bottom or in diagonals.
The following table defines the number of TWIPs to move left or right before to draw the 2nd character when the 1st one was drawn right before it. For instance, the letters AV may be drawn really close so the V is written over the A. To the contrary, WI may be seperated some more so the I doesn't get merged to the top of the W.
The computation to move the drawing pen is done as follow:
/* writing 'AV' */ x += f_font2_advance['A'] + f_kerning['AV'].f_kerning_adjustment;
where 'x' is the position at which f_kerning_code1 was draw.
Fig 1. Kerning "AV" and "WI"
The width of the line is in TWIPS (1/20th of a pixel).
The f_start_cap_style and f_end_cap_style can be:
Round is the default, the way line caps looked before version 8. No Cap means that nothing is added at the tip of the line. This means the line stops exactly where you say it should end. The Square Cap is like the No Cap, but it has the cap which is about Width / 2.
The f_join_style can be:
Each time a line is multiple segments, each segment join is rendered using this definition. A Round Join is what we had before. A Bevel Join is a straight line between the end edges of each line (rectangle representing a line.) The Miter Join is similar to a Bevel, except that you can control the length between the tips and the closure of the line. When the miter limit factor is large, it continues the edges of the lines and it looks like triangles or squares.
The f_no_hscale and f_no_vscale flags, when set to 1, request that the stroke thickness not be scaled along with the object.
When f_pixel_hinting is set to 1, the SWF Player forces all the anchors to be placed on a pixel (it ignores sub-pixels.) This can be useful to create small objects which you do not want blurry.
The f_no_close can be set to 1 to request that the first and last points be rendered with caps rather than a join even if they are equal (and thus close the shape.)
The f_miter_limit_factor field is defined whenever the join is set to Miter Join (2). The value is unsigned from 0.0 to about 255.0. Note that under 1.0, it has no effect.
The array of line styles starts with a counter. When DefineShape is used, the counter can be any value from 0 (no style) to 255. When DefineShape2 or DefineShape3 are used, the value 255 is reserved so you can declare more than 255 styles (up to 65535.)
By default...
Scale is a ratio. Rotate is an angle in radian. Translate is in TWIPs (1/20th of a pixel.)
The array of shape records starts with a set of styles definition and is followed by shape records. The list of shape records ends with a null record.
Note that f_shape_records_morph cannot include any reference to styles and lines, nor include new styles. It is likely that the f_styles_count will always be 0x11. Also, it is always byte aligned.
Since version 7 of SWF, there is a new way to create a function allows you to not only name parameters but also to put their content in a register. This is done by specifying a register number along an (optional) parameter name.
The f_param_register specifies whether the corresponding parameter will be saved in1:
Note that the auto-generated variables (those defined by the "preload" flags to the Declare Function (V7)) are also saved in registers. You have to make sure you save your own variables in registers that are not already in use by these system variables2.
The f_param_name string will be ignored whenever the f_param_register parameter is not zero. Otherwise, it is used to save the corresponding parameter in a variable of that name. Since up to 255 registers can be used, it rarely will be necessary to save local variables in named variables when using the Declare Function (V7) action.
Each color component is a value from 0 (no intensity) to 255 (full intensity).
The color components can be set to any value from 0 (no intensity) to maximum intensity (255).1
It is important to note that even fully transparent pixels may not have their red, green, blue components set to 0. This is useful if you want to add a value to the alpha channel using one of the color transformation matrices. In that case, using all 0's would generate a black color.
f_red = orginal red * f_alpha / 255
The rectangles are very well compressed in an SWF file. These make use of a 5 bits size which specifies how many bits are present in the following four fields. Don't forget that the bits are read from the MSB to the LSB and in big endian like when multiple bytes are necessary.
Fonts uses this declaration. It does not include any style (fill or line) definitions. The drawing will use fill 0 when the inside of the shape should not be drawn and 1 when it is to be filled. The line style should not be defined.
The shape records are typed. Depending on that type, the contents vary. The following defines one structure for each type. The shape record is a union of these structures.
It is important to note that the f_shape_move_x and f_shape_move_y are not deltas from the current point, but a position from the current shape origin. All the other positions are defined as deltas from the previous position, including the anchors which are deltas from the control point position!
The control point defines how much the curve is curved. Please, see The geometry in SWF for more information.
The array of shape records starts with a set of style definitions and is followed by shape records. The last record is marked by a null record.
Information on how to playback a sound effect. These are found in a StartSound and a DefineButtonSound.
The f_sound_id_ref is a reference to an earlier DefineSound tag.
The f_stop_playback can be set to 1 in which case the sound stops as soon as the next ShowFrame is reached. All the other flags should be set to 0 when this one is 1.
The f_no_multiple flag indicates whether the same sound effect can be played more than once at a time.
The f_in/out_point indicate the start and end points where the sound should start playing and where it will end. f_in_point should always be smaller than f_out_point. By default, f_in_point is taken as being 0 and f_out_point is set to the f_sound_samples_count value.
The f_loop_count defines the number of times the sound will be played back. I don't know yet whether there is a special value which means playback forever.
This structure is found in the shape with style and change style structures.
Note that the line & fill bits are declared as "unsigned char" because they will always be aligned. The proper definition would probably be a bit field though.
The tag and size are saved in a 16 bits little endian unsigned integer. The tag is always aligned to a byte (not a bit). The size is defined in the lower 6 bits. And the short value is in a little endian format as expected by the declaration. If the size is 63 (0x3F), then another 4 bytes are read for the size. This is used for really large tags such as fonts with many characters, audio, video, or images.
WARNING: The following tags only support the long format (i.e. f_tag_and_size & 0x3F == 0x3F even if the size is less than 63.) These are:
The swf_text_entry structure defines a list of characters and the number of TWIPs to skip to go to the next character. Note that f_advance is a signed value. Thus you can write characters from right to left which is useful to write characters in languages such as Arabic in a native way. The number of bits used to define each field of this structure is defined in the DefineText or DefineText2 tags.
The swf_text_record structure is a union composed of a swf_text_record_setup definition followed by characters. Multiple records can follow each others. The list is ended with one byte set to 0.
WARNING: it seems that Macromedia didn't think about a file having two records of type glyph one after another (it makes their plugins crash); you will have to insert a setup record between each glyph record (the setup can be empty: i.e. add one byte equal to 0x80
). The very first setup has to at least define the font.
NOTE: this has been corrected by Macromedia it now shows as one structure including the style and an array of glyphs. This fixes the problem at once. It however makes the structure look a bit more complicated.
The very first byte of a record determines its type. When it is set to zero, it is the end of text records. In all versions (though it was not defined that way before), you need to alternate the setup and glyph records. It seems that even older versions would support more than 127 characters, however, if you plan to use 128 to 255 characters in a text records, I recommend you create a version 7 movie. So, in other words, go ahead and use the swf_text_record_string with f_glyph_count set to a value from 1 to 127 in a version 1 to 6 movie.
To make sure that none of the setup records are recognized as the end record, you should always set the bit 7 to 1 (f_type_setup). You don't otherwise have to have any font, color or displacement definition in setups (except the very first which needs to specify a font).
The f_glyph_count must be at least 1. If you don't have any characters, just don't create a text entry.
The f_move_x and f_move_y always specify a position from the origin where the text object is placed like in a shape.
Images without an alpha channel which are saved using 32 bits (format 5) use XRGB colors.
The f_pad field should be set to zero or 255.
The color components can be set to any value from 0 (no intensity) to maximum intensity (255).
An array of alignment zones defines hints about glyphs defined in a DefineFont3.
The f_zone_count specifies how many zones are defined in a zone array. In version 8 of SWF, the count must be set to 2.
The f_zone_data is an array of zones, each defining a position and a size.
The f_zone_x and f_zone_y defines whether the horizontal and vertical positions and sizes are defined. At least one of these flag shall be set to 1.1
The swf_zone_array includes an array of zone data as described below:
The f_zone_position specifies the X or Y coordinate. The array can either include only horizontal, only vertical or both sets of coordinates.
The f_zone_size specifies the Width or Height of the zone.