AS3: runtime font loading (embedding)
Flash is wonderful technology and has many advantages. Before a couple of years it was really popuplar to use it for displaying fonts that are not installed on the user's machine. Flash is still powerfull tool for such kind of tasks. These days I worked on a project which had to use a lot of fonts. It wasn't possible to embed all of them so I decided to implement runtime embedding.
Flash still can't load directly a font file. That's why I embeded the font in a swf that had to be loaded later. In my case it was better to create different swf file for every font, but if you prefer you can put all the fonts in only one file. So create a new flash document and open the library panel (press F11). Click on the little button in the top right corner.[1]and choose New Font.... [2]Fill the Character ranges part, choose your font and remember the value of the Family field. After that move to the second tab ActionScript. [3]Check Export for ActionScript and Export in frame 1. Type a class name of the font (you will need this name later). Everything is ready and you can compile the swf that will be used. The following code loads the produced swf file and adds a text field, which uses the font.
package {
import flash.display.Loader;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLRequest;
import flash.text.Font;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
public class App extends MovieClip {
public static
const FONT_NAME: String = "Brush Script Std";
public static
const FONT_EXPORT_NAME: String = "FontBrushScript";
public static
const FONT_FILE_NAME: String = "font/BrushScript.swf";
function App(): void {
var loader: Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onFontLoaded);
loader.addEventListener(IOErrorEvent.IO_ERROR, onFontLoadingFailed);
loader.addEventListener(IOErrorEvent.NETWORK_ERROR, onFontLoadingFailed);
loader.addEventListener(IOErrorEvent.VERIFY_ERROR, onFontLoadingFailed);
loader.addEventListener(IOErrorEvent.DISK_ERROR, onFontLoadingFailed);
loader.load(new URLRequest(FONT_FILE_NAME));
}
private
function onFontLoaded(e: Event): void {
trace("Successfully loaded " + FONT_EXPORT_NAME + " (" + FONT_FILE_NAME + ")");
if (e.target.applicationDomain.hasDefinition(FONT_EXPORT_NAME)) {
var FontClass: Class = e.target.applicationDomain.getDefinition(FONT_EXPORT_NAME) as Class;
Font.registerFont(FontClass);
addTextField();
} else {
trace("Missing " + FONT_EXPORT_NAME + "!");
}
}
private
function onFontLoadingFailed(e: IOErrorEvent): void {
trace("Missing " + FONT_FILE_NAME);
}
private
function addTextField(): void {
trace("Adding text field ...");
var format: TextFormat = new TextFormat();
format.font = FONT_NAME;
format.size = 45;
format.color = 0x9f0000;
format.bold = true;
var field: TextField = new TextField();
field.defaultTextFormat = format;
field.text = "Embed font at runtime.";
field.x = field.y = 35;
field.embedFonts = true;
field.autoSize = TextFieldAutoSize.LEFT;
addChild(field);
}
}
}
There are three major constants in the code:
public static
const FONT_NAME: String = "Brush Script Std";
public static
const FONT_EXPORT_NAME: String = "FontBrushScript";
public static
const FONT_FILE_NAME: String = "font/BrushScript.swf";
The first one FONT_NAME is used in the TextFormat definition. You should use the real family name of the font. The second one is the name of the class that you have to fill. And the last one is just the path to the swf file. You can download the full example's code here.