Fonts and Text
Fonts and Text Contents.............................................................................................................................. 1
Fonts and Text..................................................................................................................................................... 1
Glyph Definitions.................................................................................................................................................. 2
The EM Square...................................................................................................................................................... 3
Converting TrueType fonts to SWF glyphs......................................................................................................... 3
Kerning and Advance Values................................................................................................................................. 4
DefineFont and DefineText................................................................................................................................... 4
A Text Example..................................................................................................................................................... 4
The DefineFont Tag............................................................................................................................................... 5
The DefineText Tag............................................................................................................................................... 6
Text Records.......................................................................................................................................................... 6
Text Record Type 1 Text Style Change Record................................................................................................. 6
Text Record Type 0 Glyph Record.................................................................................................................... 7
Glyph Entry.......................................................................................................................................................... 7
Mapping to Native Fonts...................................................................................................................................... 8
DefineFont2........................................................................................................................................................... 8
Kerning Record...................................................................................................................................................... 9
DefineText2......................................................................................................................................................... 10
SDK Examples....................................................................................................................................................... 10
Edit Text Fields................................................................................................................................................... 10
SDK Examples....................................................................................................................................................... 12
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 SWF format 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 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 SWF file, even if the desired font is already on the client machine.
To guarantee text is reproduced correctly, 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.
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 Flash player scales the glyph from EM coordinates to point-size coordinates.
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. 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 Flash movies to be used for large bodies of text with small point sizes.
TrueType fonts can be readily converted to SWF glyphs. A simple algorithm can replace the Quadratic B-splines (used by TrueType) with Quadratic Bezier curves (used by 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.
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 fonts ascent, descent, and some extra spacing to prevent lines of text from colliding.
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 SWF, they should be scaled to fit an EM square of 1024.
TrueType glyphs are defined using Quadratic B-Splines, which can be easily converted to the Quadratic Bezier curves used by 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.
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 SWF glyphs is as follows:
1.
Negate the y-coordinate. (In TrueType the y-axis points up, in 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.
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.
SWF stores kerning information as an advance value. That is, the horizontal advance from one glyph to another. 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.
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:
·
Type 0 Glyph
Information.
A Type 0 Record contains an array of indices into the
glyph table of the current font.
Characters are not referred to by their ASCII or Unicode values, but by
an index into the glyph table. Type 0
Records also include the advance value for each character in the text string.
·
Type 1
Style Information.
A Type 1 Record
selects the current font, color, and point size, as well as the position of
next character in the text. These styles apply to all characters that follow,
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.
Note: The DefineFont tag
must always come before the DefineText tag that refers to it.
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 fonts 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 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
(See class FDTDefineFont in the Flash File Format SDK)
Field |
Type |
Comment |
Header |
RECORDHEADER |
Tag ID = 10 |
FontId |
UI16 |
ID for this character |
OffsetTable |
UI16[nGlyphs] |
Array of shape offsets |
ShapeTable |
SHAPE[nGlyphs] |
Array of shapes |
The DefineText tag
defines a block of text. It describes the
font, size, color, and exact position of every character in the text
object.
(See class FDTDefineText
in the Flash File Format SDK)
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 |
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 come in two flavors; Type 0 and Type 1. The first bit of the TEXTRECORD determines the type.
(See class FTextRecord in the Flash File Format SDK)
TEXTRECORD |
||
Field |
Type |
Comment |
TextRecordType |
UB[1] |
0 = glyph record 1 = text style 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.
(See class FTextChangeRecord
in the Flash File Format SDK)
TEXTRECORDTYPE1 (Text Style Change Record) |
||
Field |
Type |
Comment |
TextRecordType |
UB[1] = 1 |
1 if text state 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 |
The
TextFontID field is used to select a previously defined font. This ID uniquely identifies a DefineFont tag
earlier in the 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).
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.
The Type 0 Text Record defines the actual characters in a text string. Characters are referred to by an index into the current fonts 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.
(See class FTextGlyphRecord in the Flash File Format SDK)
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 |
The TextGlyphCount field defines the number of characters in this string, and the size of the GLYPHENTRY table.
The GLYPHENTRY structure describes a single character in a line of text. It is comprised of an index into the current fonts glyph table, and an advance value. The advance value is the horizontal distance between the reference point of this character, and the following character.
(See class FGlyphEntry in the Flash File Format SDK)
GLYPHENTRY |
||
Field |
Type |
Comment |
TextGlyphIndex |
UB[nGlyphBits] |
Glyph index into current
font |
TextGlyphAdvance |
SB[nAdvanceBits] |
X advance value for glyph |
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 machines 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.
(See class FDTDefineFontInfo in the Flash File Format SDK)
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 |
UB[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 wideChars = 1
U16[nGlyphs] |
Glyph to code table |
The DefineFont2 tag
extends the functionality of DefineFont. Enhancements include:
·
32-bit
entries in the OffsetTable, for fonts with more than 64K glyphs.
·
Mapping
to native fonts, by incorporating all the functionality of DefineFontInfo.
·
Ascent,
descent and leading information.
·
An
advance table that defines the advance for each glyph (in EM square
coordinates).
·
A
bounds table that defines the bounding-box of each glyph (in EM square
coordinates).
·
A
table of kerning pairs that defines the distance between pairs of glyphs.
(See class FDTDefineFont2 in the Flash File Format SDK)
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, |
|
FontDescent |
If FontFlagsHasLayout is 1, |
|
FontLeading |
If FontFlagsHasLayout is 1, |
|
FontAdvanceTable |
If FontFlagsHasLayout is 1, |
|
FontBoundsTable |
If FontFlagsHasLayout = 1, |
Not used in Flash 4 Player |
FontKerningCount |
If FontFlagsHasLayout is 1, |
Not used in Flash 4 Player |
FontKerningTable |
If FontFlagsHasLayout is 1, |
Not used in Flash 4 Player |
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
(See class FKerningRec
in the Flash File Format SDK)
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. |
Note: FontBoundsTable,
FontKerningCount and FontKerningTable are not used in the 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.
(See class FDTDefineText2 in the Flash File Format SDK)
DefineText2 |
||
Field |
Type |
Comment |
Header |
RECORDHEADER |
Tag ID = 33 |
TextId |
UI16 |
ID for this character |
TextBounds |
Bounding box of the text |
|
TextMatrix |
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 |
The SDK contains C++ examples that demonstrate how to create fonts and text in SWF:
·
FExampleFont.cpp uses the low-level
manager to create a simple two-glyph font with the letters b and o, and a
text object with the string bob.
·
HFExampleFont.cpp uses the high-level
manager to create a font with the glyphs F, L, A, S, and H. The glyphs are added to the HFFont object
and associated with ASCII/Unicode equivalents.
A text object is created by referencing the glyphs by their
ASCII/Unicode values.
As well as static text, SWF (version 4.0) 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 Flash text. Unlike HTML, a text entry box in a 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 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.
(See class FDTDefineEditText in the Flash File Format SDK)
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
disabaled. |
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, indents 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 U8 |
0 = Left |
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 |
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. |
Note: Fonts used by DefineEditText must be defined using DefineFont2, not DefineFont.
The SDK contains C++ examples that demonstrate how to create editable text fields in SWF:
·
FExampleEditText.cpp uses the low-level
manager to create a single-line editable text field, which contains the text
start initially. The
FDTDefineEditText object does not define any outlines (glyphs), it uses the
default font built into the player.