Font embedding in flex

Embedding fonts is always tricky in flash. Since I work on exhibits that load dynamic content my font needs are relatively simple: take a font, make it available to flash, and use it to render type. I need styles and weights (flash understands bold, italic, and bold/italic). And I need it to be reliable. After digging around for a while I am currently using the following solution.

In my code library (com.rshields), I created a fonts package. Inside this package I've placed regularly used fonts. Note that these fonts must be otf or ttf for this to work. Then, for each font, I've created a class defining that font. If the font contains multiple files (for bold and/or italic) I create another class with the additional files; this makes the bold and italic tags work in htmlText. If the font has an additional style I wish to use (say, for example, Black), I create a class for the style with a new name and use the font in text using a font face tag. Then, in my main class, I import the fonts I want to use, register them with flash.text.Font, tell my TextFields to use the embedded font (targetField.embedFonts = true), set the TextFormat for the TextField to the name I gave the font, and, finally, set the TextField's html text. It's a long process, but it yields true embedded font functionality.

Code time... Let's embed the font "CustomFont" in Standard and Bold face, then add CustomFont's Black face. In the package for your font library, place the CustomFont.otf, CustomFontBold.otf, and CustomFontBlack.otf files. Then create 3 new as files, CustomFontEmbed.as, CustomFontBoldEmbed.as, and CustomFontBlackEmbed.as. We embed the fonts using compiler directives pointing at the correct files, then declare the class. The contents of these files should be (note that package and the file path will depend on your setup):

CustomFontEmbed.as

package com.rshields.fonts
{
  import flash.text.Font;
  [Embed(source='/com/rshields/fonts/CustomFont.otf', fontName='CustomFont', mimeType='application/x-font', advancedAntiAliasing='true', fontWeight='normal')]
  public class CustomFontEmbed extends Font {};
}

CustomFontBoldEmbed.as

package com.rshields.fonts
{
  import flash.text.Font;
  [Embed(source='/com/rshields/fonts/CustomFontBold.otf', fontName='CustomFont', mimeType='application/x-font', advancedAntiAliasing='true', fontWeight='bold')]
  public class CustomFontBoldEmbed extends Font {};
}

CustomFontBlackEmbed.as

package com.rshields.fonts
{
  import flash.text.Font;
  [Embed(source='/com/rshields/fonts/CustomFontBlack.otf', fontName='CustomFontBlack', mimeType='application/x-font', advancedAntiAliasing='true', fontWeight='normal')]
  public class CustomFontBlackEmbed extends Font {};
}

Note that the first 2, Standard and Bold, use the same fontName, 'CustomFont', but we tell flash that the Bold style has a fontWeight of 'bold' (supported fontStyle parameters are normal and italic, supported fontWeight parameters are normal and bold). The third one, Black, is a style not (yet? hopefully) supported by flash, so we just give it a different fontName, 'CustomFontBlack'.

Now we go to our Main.as class, import the fonts, and register them. This only needs to be done once in your main class. Once the fonts are registered, child classes with TextFields can use these fonts.

package
{
  import com.rshields.fonts.*; // importing all of my embeds, but you can just import specific fonts and styles by doing multiple imports
  import flash.display.Sprite;
  import flash.text.Font;

  public class Main extends Sprite
  {
    public function Main() {
      super();
      Font.registerFont(CustomFontEmbed);
      Font.registerFont(CustomFontBoldEmbed);
      Font.registerFont(CustomFontBlackEmbed);
...etc...

We're all set to use the fonts! Let's assume you have a child class named MyTextBox. MyTextBox will create a TextField, set the style to CustomFont, state that the TextField is using embedded fonts, and then write 3 lines, Hello World, in Standard, Bold, and Black.

package myProject
{
  import flash.display.Sprite;
  import flash.text.TextField;
  import flash.text.TextFormat;

  public class MyTextBox extends Sprite
  {
    private static var _defaultFormat:TextFormat = new TextFormat("CustomFont", 12, 0xAAAAAA);

    public function MyTextBox()
    {
      super();
      var myText:TextField = new TextField();
      myText.defaultFormat = _defaultFormat;
      myText.embedFonts = true;
      myText.multiLine = true;
      myText.width = 200;
      myText.htmlText = 'Hello World<br /><b>Hello World</b><br /><font face="CustomFontBlack">Hello World</font>';
      this.addChild (myText);
    }
  }
}

And there we have it. Note that embedded fonts have certain benefits and drawbacks over using system (or device) fonts. Embedding fonts increases file size, sometimes a lot, and this translates into longer "Loading..." progress time. However, embedded fonts can be rotated, alpha'ed, etc., without suddenly disappearing from the stage (as device fonts are prone to do). But by embedding entire font sets it is now relatively safe to load in external data and render it in the correct font, giving the coder and the designer much more control over the look of their applications.