Macromedia Flash File Format (SWF)

recompiled with RAW HTWL

Fonts and Text


Introduction Basic Types Display List Control Tags
Shapes (Examples Shapes) Gradients Buttons
Sprites Fonts and Text Shape Morphing Bitmap
Sounds Actions ActionScripts Reference

Font and Text Contents

Fonts and Text
Glyph Definitions
The EM Square
Converting TrueType fonts to Macromedia Flash (SWF) glyphs
Kerning and Advance Values
DefineFont and DefineText
A Text Example
The DefineFont Tag
The DefineText Tag
Text Records
Text Record Type 1 — Text Style Change Record
Text Record Type 0 — Glyph Record
Glyph Entry
Mapping to Native Fonts
DefineFont2
Kerning Record
DefineText2
Edit Text Fields

Fonts and Text

Flash text has been designed to be completely device independent. Text is guaranteed to look exactly the same on every device, regardless of which fonts are installed on the client machine. The Macromedia Flash File Format (SWF) achieves this by including the exact shape of every letter, number (or other text character) used in the movie. These character shape definitions are called glyphs.

Defining each and every glyph increases the size of a Macromedia Flash (SWF) file, particularly if the font is complex. However, it is a necessary tradeoff. At design time, Flash knows nothing about the capabilities of the client device, therefore glyphs must always be included in the Macromedia Flash (SWF) file, even if the desired font is already on the client machine. To guarantee text is reproduced correctly, Macromedia Flash (SWF) also includes the exact position of every character in a text block. Again, this adds to the file size, but allows sophisticated text layout effects (like kerning and text wrapping) without requiring a complex layout engine built into the Flash player.
letter b

Glyph Definition

Glyphs are defined once in a standard coordinate space called the EM square. The same set of glyphs are used for every point size of a given font. To render a glyph at different point sizes, the Macromedia Flash player scales the glyph from EM coordinates to point-size coordinates.

Macromedia Flash fonts do not include any hinting information for improving the quality of small font sizes. However, antialiasing dramatically improves the legibility of down-scaled text. Macromedia Flash text remains legible down to about 12-points (viewed at 100%). Below that, text may appear fuzzy and blurred. In any case, it is rare for Macromedia Flash movies to be used for large bodies of text with small point sizes.

TrueType fonts can be readily converted to Macromedia Flash (SWF) glyphs. A simple algorithm can replace the Quadratic B-splines (used by TrueType) with Quadratic Bezier curves (used by Macromedia Flash (SWF)).

Example:
To the left is the glyph for the TrueType letter 'b' of Monotype Arial. It is made up of curved and straight edges. Squares indicate on-curve points, and crosses indicate off-curve points. The black circle is the reference point for the glyph. The blue outline indicates the bounding-box of the glyph.

letter Q

The EM Square

The EM square is an imaginary square that is used to size and align glyphs. The EM square is generally large enough to completely contain all glyphs, including accented glyphs. It includes the font’s ascent, descent, and some extra spacing to prevent lines of text from colliding.

Macromedia Flash (SWF) glyphs are always defined on an EM square of 1024 by 1024 units. Glyphs from other sources (such as TrueType fonts) may be defined on a different EM square. To use these glyphs in Macromedia Flash (SWF), they should be scaled to fit an EM square of 1024.

Converting TrueType fonts to Macromedia Flash (SWF) glyphs

TrueType glyphs are defined using Quadratic B-Splines, which can be easily converted to the Quadratic Bezier curves used by Macromedia Flash (SWF).

A TrueType B-Spline comprises one on-curve point, followed by many off-curve points, followed by another on-curve point. The mid-point between any two off-curve points is guaranteed to be on the curve. A SWF Bezier curve comprises one on-curve point, followed by one off-curve point, followed by another on-curve point.

The conversion from TrueType to Macromedia Flash (SWF) curves involves inserting a new on-curve point at the mid-point of two successive off-curve points.

Example:
To the left is a four point B-Spline. P0 and P3 are on-curve points. P1 and P2 are successive off-curve points.

This curve can be represented as two Quadratic Bezier curves by inserting a new point M, at the mid-point of P1,P2. The result is two Quadratic Bezier curves; P0,P1,M and M,P2,P3.

The complete procedure for converting TrueType glyphs to Macromedia Flash (SWF) glyphs is as follows:
  1. Negate the y-coordinate. (In TrueType the y-axis points up, in Macromedia Flash (SWF) the y-axis points down)
  2. Scale the x and y co-ordinates from the EM square of the TrueType font, to the EM square of the SWF glyph (always 1024)
  3. Insert an on-curve (anchor) point at the mid-point of each pair of off-curve points.
For a more complete discussion of this algorithm see: http://www.icce.rug.nl/erikjan/bluefuzz/beziers/beziers/node1.html

AV, AO

Kerning and Advance Values

Kerning defines the horizontal distance between two glyphs. This distance may be smaller or larger than the width of the left-hand glyph. Some kerning pairs are more aesthetically pleasing if they are moved closer together.

Macromedia Flash (SWF) stores kerning information as an advance value. That is, the horizontal advance from one glyph to another. Macromedia Flash (SWF) stores an advance value for every character in a text block.

In the example to the right, the ‘A’ glyph overlaps the ‘V’ glyph. In this case the advance is narrower than the width of the ‘A’ glyph.

DefineFont and DefineText

Fonts and text are defined using two tags:
  1. The DefineFont tag defines a set of glyphs.
  2. The DefineText tag defines the text-string that is displayed in the font.
The DefineFont tag defines all the glyphs used by subsequent DefineText tags. DefineFont includes an array of SHAPERECORDs, which describe the outlines of the glyphs. (These shape records are the same records used by DefineShape to define non-text shapes) To keep file size to a minimum, only the glyphs actually used in the text block are included in the DefineFont tag. For example, to display the word “hello”, only the glyphs ‘h’, ‘e’, ‘l’, and ‘o’ are defined.

The DefineText tag stores the actual text string(s) to be displayed. It also includes the bounding box of the text object, a transformation matrix, and style attributes such as color, and point size.

DefineText contains an array of TEXTRECORDs, of which there are two types: Note: The DefineFont tag must always come before the DefineText tag that refers to it.

A Text Example

Suppose you want to display the text “bob” in the Arial font, with a point size of 24.

First, you must define the glyphs with a DefineFont tag. The glyph table has two SHAPERECORDs; At index 0 is the shape of a lower-case ‘b’ (see diagram). At index 1 is the shape of a lower-case ‘o’. (The second ‘b’ in bob is a duplicate, and is not required). DefineFont also includes a unique ID so it can be selected by the DefineText tag.

Next you define the text itself with a DefineText tag. The first text record must be a Type 1 record. It sets the position of the first character, selects the Arial font (using the unique ID), and sets the point size to 24, so the font is scaled to the correct size. (Remember that glyphs are defined in EM coordinates – the actual point size is part of the DefineText tag).

The second text record is a Type 0 record. It contains an array of GLYPHENTRYs. Each glyph entry contains an index into the font’s shape array. In this example, the first glyph entry has index 0 (which corresponds to the ‘b’ shape), the second entry has index 1 (the ‘o’), and the third entry has index 0 (‘b’ again). Each GLYPHENTRY also includes an advance value for accurately positioning the glyph.

The diagram below illustrates how the DefineText tag interacts with the DefineFont tag:


The DefineFont Tag

The DefineFont tag defines the shape outlines of each glyph used in a particular font. Only the glyphs that are used by subsequent DefineText tags are actually defined.

The FontId uniquely identifies the font. It can be used by subsequent DefineText tags to select the font.

The offset table and shape table are used together. These tables have the same number of entries, and there is a one-to-one ordering match between the order of the offsets, and the order of the shapes.
The offset table points to locations in the shape table. Each offset entry stores the difference (in bytes) between the start of the offset table and the location of the corresponding shape:
Location of ShapeRecord[n] = StartOfOffsetTable + OffsetTable[n]
Because the ShapeTable immediately follows the OffsetTable, the number of entries in both tables can be inferred by dividing the first offset by two:
Shape count = OffsetTable[0] / 2
     DefineFont     
     Field           Type           Comment     
     Header           RECORDHEADER           Tag ID = 10     
     FontId           UI16           ID for this character     
     OffsetTable           UI16 [nGlyphs]           Array of shape offsets     
     Shape Table           SHAPE [nGlyphs]           Array of shapes     
    SwfJava v0.0: how to create a DefineFont object    
    new DefineFont (    
        int id,    
        Shape [] shapes    
    );    


    XWF v0.0: how to declare a DefineFont tag    
    <DefineFont id="(ID)" >    
        <Shape ... />    
        <Shape ... />    
        ...    
    </DefineFont>    


The DefineText Tag

The DefineText tag defines a block of text. It describes the font, size, color, and exact position of every character in the text object.
     DefineText     
     Field           Type           Comment     
     Header           RECORDHEADER           Tag ID = 11     
     TextId           UI16           ID for this character     
     TextBounds           RECT           Bounds of the text     
     TextMatrix           MATRIX           Matrix for the text     
     TextGlyphBits           nGlyphBits = UI8           Bits in each glyph index     
     TextAdvanceBits           nAdvanceBits = UI8           Bits in each advance value     
     TextRecords           TEXTRECORD[zero or more]           Text records     
     TextEndOfRecordsFlag           UI8 = 0           Always set to zero     
    SwfJava v0.0: how to create a DefineText object    
        
    {the Java low-level function for this tag is not fully satisfying yet}    
        


    XWF v0.0: how to declare a DefineText tag    
    <DefineText id="(ID)" >    
        <Matrix ... />    
        <textrecord ... />    
        <textrecord ... />    
        ...    
    </DefineText>    
        
    a textrecord can be a StyleText or a Glyph    



The TextBounds field is the rectangle that completely encloses all the characters in this text block.

The TextGlyphBits field defines the number of bits used for the TextGlyphIndex field in each GLYPHENTRY record.

The TextAdvanceBits field defines the number of bits used for the TextGlyphAdvance field in each GLYPHENTRY record.

Text Records

Text Records come in two flavors; Type 0 and Type 1. The first bit of the TEXTRECORD determines the type.
     TextRecord     
     Field           Type           Comment     
     TextRecordType           UB [1]           0 = glyph record, 1 = text style record     

Text Record Type 1 — Text Style Change Record

A Type 1 Record sets text styles for subsequent characters. It can be used to select a font, change the text color, change the point size, or insert a line break. The new text styles apply until another type 1 record changes the styles.
The array of text records always begins with a type 1 record to set the initial position and style.
     TextRecordType1 (Text Style Change Record)     
     Field           Type           Comment     
     TextRecordType           UB [1] = 1           1 if text stage change record     
     TextReserved           UB [3]           Reserved — always 0     
     TextHasFont           HasFont = UB [1]           1 if text font specified     
     TextHasColor           HasColor = UB [1]           1 if text color specified     
     TextHasYOffset           HasYOffset = UB [1]           1 if Y offset specified     
     TextHasXOffset           HasXOffset = UB [1]           1 if X offset specified     
     TextFontID           if hasFont UI16           Font ID for following text     
     TextColor           If hasColor RGB
If this record is part of a DefineText2 tag then RGBA
    
     Font color for following text     
     TextXOffset           If hasXOffset SI16           Font X offset for following text     
     TextYOffset           If hasYOffset SI16           Font Y offset for following text     
     TextHeight           If hasFont UI16           Font height for following text     
    SwfJava v0.0: how to create a TextRecordType1 object    
    new StyleTextRecord (    
        boolean hasFont, int fontID, int fontHeight,    
        boolean hasColor, Primitive color,    
        boolean hasXOffset, int xOffset,    
        boolean hasYOffset, int yOffset    
    );    
        
    a Primitive can be a RGB or a RGBA    


    XWF v0.0: how to declare a StyleText element    
    <StyleText    
        [fontID="(ID)" fontHeight="(int)"]    
        [color="#3366FF"] [color="#3366FF/CC"]    
        [xOffset="(int)"] [yOffset="(int)"]    
    />    



The TextFontID field is used to select a previously defined font. This ID uniquely identifies a DefineFont tag earlier in the Macromedia Flash (SWF) file.

The TextHeight field defines the point size of the font in twips. For example, a point size of 50 is equivalent to a TextHeight of 1000. (50 * 20 = 1000).
Each coordinate in all following glyphs will be multiplied by a ratio fontHeight/1024, where 1024 is the size of the EM square.

The TextXOffset field defines the offset from the left of the TextBounds rectangle to the reference point of the glyph. Typically, the reference point is on the baseline, near the left side of the glyph (see example glyph diagram). The TextXOffset is generally used to create indented text, such as right-justified text. If there is no TextXOffset specified, the offset is assumed to be zero.

The TextYOffset field defines the offset from the top of the TextBounds rectangle to the reference point of the glyph. Typically, the reference point is on the baseline, near the left side of the glyph (see example glyph diagram). The TextYOffset is generally used to insert line breaks, by moving the text position to start of a new line.

Text Record Type 0 — Glyph Record

The Type 0 Text Record defines the actual characters in a text string. Characters are referred to by an index into the current font’s glyph table, not by an ASCII or Unicode value. A Type 0 Text Record contains a group of characters that all share the same text style, and are on the same line of text.
     TextRecordType0 (Glyph Record)     
     Field           Type           Comment     
     TextRecordType           UB [1] = 0           0 if text glyph record     
     TextGlyphCount           nGlyphs = UB [7]           Number of glyphs in record     
     TextGlyphEntries           GLYPHENTRY[nGlyphs]           Glyph entry — see below     
    SwfJava v0.0: how to create a TextRecordType0 object    
    new GlyphTextRecord (    
        Glyph [] glyphs    
    );    



The TextGlyphCount field defines the number of characters in this string, and the size of the GLYPHENTRY table.

Glyph Entry

The GLYPHENTRY structure describes a single character in a line of text. It is comprised of an index into the current font’s glyph table, and an advance value. The advance value is the horizontal distance between the reference point of this character, and the following character.
     GlyphEntry     
     Field           Type           Comment     
     TextGlyphIndex           UB [nGlyphBits]           Glyph index into current font     
     TextGlyphAdvance           SB [nAdvanceBits]           X advance value for glyph     
    SwfJava v0.0: how to create a GlyphEntry object    
    new Glyph (    
        int index,    
        int advance    
    );    


    XWF v0.0: how to declare a Glyph element    
    <Glyph index="(int)" advance="(int)" />    


Mapping to Native Fonts

Macromedia Flash (SWF) also supports the use of native fonts. Rather than using the glyph outlines in the DefineFont tag, fonts can be rendered using the client machine’s font engine. Since most native font engines include hinting techniques, they may produce better results at very small point sizes.

The DefineFontInfo tag defines the mapping of a Flash font to a native font. It includes the font name, font style – bold, italic, or plain, and the encoding scheme used – ANSI, Unicode or ShiftJIS. It also defines a mapping of glyph indices to character codes. Thus if ‘a’ were the first character in your DefineFont tag, the DefineFontInfo tag would map index zero to the character code for ‘a’.
     DefineFontInfo     
     Field           Type           Comment     
     Header           RECORDHEADER           Tag ID = 13     
     FontID           UI16           Font ID this information is for     
     FontNameLen           NameLen = UI8           Length of font name     
     FontName           UI8 [nameLen]           Name of the font     
     FontFlagsReserved           UI8 [2]           Reserved bit fields     
     FontFlagsUnicode           UB [1]           Unicode character codes     
     FontFlagsShiftJIS           UB [1]           ShiftJIS character codes     
     FontFlagsANSI           UB [1]           ANSI character codes     
     FontFlagsItalic           UB [1]           Font is italic     
     FontFlagsBold           UB [1]           Font is bold     
     FontFlagsWideCodes           WideChars = UB [1]           if 1 codeTable is UI16s else UI8s     
     CodeTable           if whideChars = 1 UI16 [nGlyphs]
if wideChars = 0 UI8 [nGlyphs]
    
     Glyph to code table     
    SwfJava v0.0: how to create a DefineFontInfo object    
    new DefineFontInfo (    
        int fontID, String fontName,    
        boolean isUnicode, boolean isShiftJIS, boolean isANSI,    
        boolean isItalic, boolean isBold,    
        int[] codes    
    );    


    XWF v0.0: how to declare a DefineFontInfo tag    
    <DefineFontInfo fontID="(ID)" fontName="(string)"    
        [unicode] [shiftJIS] [ANSI]    
        [italic] [bold]    
    >    
        <CHAR code="(int)" />    
        <CHAR code="(int)" />    
        ...    
    </DefineFontInfo>    


DefineFont2

The DefineFont2 tag extends the functionality of DefineFont. Enhancements include:
     DefineFont2     
     Field           Type           Comment     
     Header           RECORDHEADER           Tag ID = 48     
     FontID           UI16           Font ID for this information     
     FontFlagsHasLayout           UB [1]           Has font metrics/layout information     
     FontFlagsShiftJIS           UB [1]           ShiftJIS encoding     
     FontFlagsUnicode           UB [1]           Unicode encoding     
     FontFlagsAnsi           UB [1]           ANSI encoding     
     FontFlagsWideOffsets           UB [1]           If 1, uses 32 bit offsets     
     FontFlagsWideCodes           UB [1]           If 1, font uses 16-bit codes, otherwise font uses 8 bit codes     
     FontFlagsItalic           UB [1]           Italic font     
     FontFlagsBold           UB [1]           Bold font     
     FontFlagsReserved           UB [8]           Reserved Flags     
     FontNameLen           NameLen = UI8           Length of name     
     FontName           UI8 [NameLen]           Name of font     
     FontGlyphCount           UI16           Count of Glyphs in font — nGlyphs     
     FontOffsetTable           If FontFlagsWideOffsets is 1, UI32 [nGlyphs] else UI16 [nGlyphs]               
     FontCodeOffset           If FontFlagsWideOffsets is 1, UI32 else UI16           Byte count from start of the FontOffsetTable to start of FontCodeTable     
     FontShapeTable           SHAPE [nGlyphs]               
     FontCodeTable           If FontFlagsWideCodes is 1, UI16 [nGlyphs] else UI8 [nGlyphs]               
     FontAscent           If FontFlagsHasLayout is 1, SI16 — Font ascender height               
     FontDescent           If FontFlagsHasLayout is 1, SI16 — Font descender height               
     FontLeading           If FontFlagsHasLayout is 1, SI16 — Font leading height               
     FontAdvance Table           If FontFlagsHasLayout is 1, SI16 [nGlyphs]               
     FontBoundsTable           If FontFlagsHasLayout is 1, RECT [nGlyphs]           Not used in Flash Player 4     
     FontKerningCount           If FontFlagsHasLayout is 1, nCount = UI16           Not used in Flash Player 4     
     FontKerningTable           If FontFlagsHasLayout is 1, KERNINGRECORD[nCount]           Not used in Flash Player 4     
    SwfJava v0.0: how to create a DefineFont2 object    
        
    {not yet implemented}    
        


Kerning Record

A Kerning Record defines the distance between two glyphs in EM square coordinates. Certain pairs of glyphs appear more aesthetically pleasing if they are moved closer together, or farther apart. The FontKerningCode1 and FontKerningCode2 fields are the character codes for the left and right characters. The FontKerningAdjustment field is a signed integer that defines the offset from the advance value of the left-hand character. The distance between two characters can be calculated like this:

Distance = FontAdvanceTable[ord(FontKerningCode1)] + FontKerningAdjustment
     KerningRecord     
     Field           Type           Comment     
     FontKerningCode1           If FontFlagsWideCodes is 1, UI16 else UI8           The character code of the left hand character.     
     FontKerningCode2           If FontFlagsWideCodes is 1, UI16 else UI8           The character code of the right hand character.     
     FontKerningAdjustment           SI16           Adjustment relative to advance values.     
    SwfJava v0.0: how to create a KerningRecord object    
        
    {not yet implemented}    
        



Note: FontBoundsTable, FontKerningCount and FontKerningTable are not used in the Macromedia Flash Player.

DefineText2

The DefineText2 tag is almost identical to the DefineText tag. The only difference is that Type 1 Text Records contained within a DefineText2 tag use an RGBA value (rather than an RGB value) to define TextColor. This allows transparent characters.
     DefineText2     
     Field           Type           Comment     
     Header           RECORDHEADER           Tag ID = 33     
     TextId           UI16           ID for this character     
     TextBounds           RECT           Bounding box of the text     
     TextMatrix           MATRIX           Transform Matrix     
     TextGlyphBits           nGlyphBits = UI8           Bits in each glyph index     
     TextAdvanceBits           nAdvanceBits = UI8           Bits in each advance value     
     TextRecords           TEXTRECORD[zero or more]           Text records     
     TextEndOfRecordsFlag           UI8 = 0           Always set to zero     
    SwfJava v0.0: how to create a DefineText2 object    
        
    {not yet implemented}    
        


Edit Text Fields

As well as static text, Macromedia Flash (SWF) (version 4) also supports editable text fields. A text field is similar to an input field in an HTML form, but it has all the typographic controls of Macromedia Flash text. Unlike HTML, a text entry box in a Macromedia Flash movie can be any color, font, size or style.

A text field is associated with a variable name where the contents of the text field are stored. The Macromedia Flash movie can perform some action based on the contents of the variable. For example, a search button could send the contents of a text field to a web server (using a GetURL action) which would display the search results.

The DefineEditText tag defines a TextField.
     DefineEditText     
     Field           Type           Comment     
     Header           RECORDHEADER           Tag ID = 37     
     TextId           UI16           ID for this character     
     Bounds           RECT           Rectangle that completely encloses the text field.     
     HasText           HasText = UB [1]           0 = text field has no default text
1 = text field initially displays the string specified by InitialText
    
     WordWrap           WordWrap = UB [1]           0 = text will not wrap and scroll sideways.
1 = text will wrap automatically when the end of line is reached
    
     Multiline           Multiline = UB [1]           0 = text field is one line only.
1 = text field is multi-line and will scroll automatically.
    
     Password           Password = UB [1]           0 = characters are displayed as typed.
1 = all characters are displayed as an asterisk.
    
     ReadOnly           ReadOnly = UB [1]           0 = text editing is enabled
1 = text editing is disabled.
    
     HasTextColor           HasTextColor = UB [1]           0 = use default color
1 = use specified color (TextColor)
    
     HasMaxLength           HasMaxLength = UB [1]           0 = length of text is unlimited.
1 = maximum length of string is specified by MaxLength.
    
     HasFont           HasFont = UB [1]           0 = use default font.
1 = use specified font (FontID) and height (FontHeight)
    
     Reserved           UB [2]           Reserved for future use     
     HasLayout           HasLayout = UB [1]           0 = no margins, idents or leading
1 = use specified margins, indents, and leading
    
     NoSelect           NoSelect = UB [1]           0 = selections enabled
1 = selections disabled
    
     Border           Border = UB [1]           0 = text field is drawn without border.
1 = text field is drawn with border.
    
     Reserved           UB [2]           Reserved for future use     
     UseOutlines           UseOutlines = UB [1]           0 = (???)     
     FontID           If HasFont UI16           Font ID for text     
     FontHeight           If HasFont UI16           Height of font in twips     
     TextColor           If HasTextColor RGBA           Color of text     
     MaxLength           If HasMaxLength UI16           Text is restricted to this length     
     Align           If HasLayout UI8           0 = Left, 1 = Right, 2 = Center, 3 = Justify     
     LeftMargin           If HasLayout UI16           Left margin in twips     
     RightMargin           If HasLayout UI16           Right margin in twips     
     Indent           If HasLayout UI16           Indent in twips     
     Leading           If HasLayout UI16           Leading in twips     
     VariableName           STRING           Name of the variable where the contents of the text field are stored.     
     InitialText           If HasText STRING           Text that is initially displayed in the text field, before it is edited.     
    SwfJava v0.0: how to create a DefineEditText object    
        
    {not yet implemented}    
        



Note: Fonts used by DefineEditText must be defined using DefineFont2, not DefineFont.
Introduction Basic Types Display List Control Tags
Shapes (Examples Shapes) Gradients Buttons
Sprites Fonts and Text Shape Morphing Bitmap
Sounds Actions ActionScripts Reference