Tuesday, June 19, 2007

Flash CS3 & ActionScript 3 Example: Loading fonts at runtime

This example demonstrates, how a movie can use fonts embedded into another movie. All resources I found so far (like AS3 Runtime Font Loading) use some Flex2 code to get it done. My example is based on pure Flash CS3.

Step 1: Create Embedded Font Movie:

Create a new movie with name embeddedFont.fla and add a new font to your Library:


Now edit the Linkage Properties:

Save the file and publish as swf.

Step 2: Create Class Files:

Create a new movie with name FontLoadingExample.as and add the following code:

package {
import flash.display.Sprite;
import flash.text.TextField;
import flash.events.Event;

public class FontLoadingExample extends Sprite {

private var textFieldFactory:TextFieldFactory;

public function FontLoadingExample() {
trace("FontLoadingExample")
textFieldFactory = new TextFieldFactory();
textFieldFactory.addEventListener(TextFieldFactory.FONT_LOADED, fontReady);
textFieldFactory.loadFont("embeddedFont.swf")
}

private function fontReady(e:Event):void {
var tf:TextField = textFieldFactory.getNewTextField("Bingo!", 0x000000, 14);
addChild(tf);
}
}
}

Now create a new movie with name TextFieldFactory.as and add the following code:

package {

import flash.text.Font;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormatAlign;
import flash.text.TextFieldType;
import flash.text.AntiAliasType;
import flash.utils.*;
import flash.display.Loader;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.net.URLRequest;
import flash.system.ApplicationDomain;
import flash.system.LoaderContext;

public class TextFieldFactory extends EventDispatcher {

public static var FONT_LOADED:String = "fontLoaded";
private static var embeddedFont:Font = null;
private var loader:Loader = null;

public function TextFieldFactory() {
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,completeHandler);
}

public function loadFont(swfURL:String):void {
var context:LoaderContext = new LoaderContext();
context.applicationDomain=ApplicationDomain.currentDomain;
loader.load(new URLRequest(swfURL), context);
}

private function completeHandler(event:Event):void {
var embeddedFontClass:Class = loader.contentLoaderInfo.applicationDomain.getDefinition("EmbeddedGaramond") as Class;
Font.registerFont(embeddedFontClass);
var embeddedFontsArray:Array = Font.enumerateFonts(false);
embeddedFont = embeddedFontsArray[0];
dispatchEvent(new Event(TextFieldFactory.FONT_LOADED));
}

public function getNewTextField(t:String, c:uint, s:uint):TextField {
if ((embeddedFont != null) && embeddedFont.hasGlyphs(t)) {
return getNewTextFieldEmbeddedFont(t, c, s)
}
else {
return getNewTextFieldDeviceFont(t, c, s)
}
}

public function getNewTextFieldEmbeddedFont(t:String, c:uint, s:uint):TextField {
trace("getNewTextFieldEmbeddedFont: "+t);

var tf:TextField = new TextField();
var fo:TextFormat = new TextFormat();

fo.font = embeddedFont.fontName;
fo.color = c;
fo.size = s
tf.defaultTextFormat = fo;
tf.autoSize = TextFieldAutoSize.LEFT
tf.type = TextFieldType.DYNAMIC;
tf.multiline = false;
tf.selectable = false;
tf.textColor = c;
tf.embedFonts = true;
tf.antiAliasType = AntiAliasType.ADVANCED;
tf.border = true;
tf.wordWrap = false;
tf.text = t;
return tf;
}

public function getNewTextFieldDeviceFont(t:String, c:uint, s:uint):TextField {
var tf:TextField = new TextField();
var fo:TextFormat = new TextFormat();

trace("getNewTextFieldDeviceFont: "+t);
fo.font = "_serif";
fo.color = c;
fo.size = s
tf.defaultTextFormat = fo;
tf.autoSize = TextFieldAutoSize.LEFT
tf.type = TextFieldType.DYNAMIC;
tf.multiline = false;
tf.selectable = false;
tf.textColor = c;
tf.embedFonts = false;
tf.border = true;
tf.wordWrap = false;
tf.text = t;
return tf;
}

}
}

Save both files.

Step 3: Create the Font Loading Movie:

Create a new movie with name FontLoadingExample.fla and and set the document class to FontLoadingExample.fla.


Save, publish and run the movie. You will see the words "Bingo!" set with the embedded font.

Flash CS3 & ActionScript 3 Example: Using hasGlyphs() with embedded fonts

This example demonstrates the hasGlyphs() function with an embedded font (no need for Flex2).

Step 1: Embed Font:

Create a new movie and add a new font to your Library:

now edit the linkage properties:




Step 2: Add Code:

Create a new text file with the name Test.as in the same folder and add the following code:

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

public class Test extends Sprite {

private var textFieldFactory:TextFieldFactory;

public function Test() {
trace("Embedded Font Test")
textFieldFactory = new TextFieldFactory();
var tf:TextField = textFieldFactory.getNewTextField("Bingo!", 0x000000, 14);
addChild(tf);
}

}
}

Now create a new text file with the name TextFieldFactory.as in the same folder and add the following code:

package {

import flash.text.Font;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormatAlign;
import flash.text.TextFieldType;
import flash.text.AntiAliasType;
import flash.utils.*;


public class TextFieldFactory {

private static var embeddedFont:Font = null;

public function TextFieldFactory() {
var embeddedFontClass:Class = getDefinitionByName("EmbeddedGaramond") as Class;
Font.registerFont(embeddedFontClass);
var embeddedFontsArray:Array = Font.enumerateFonts(false);
embeddedFont = embeddedFontsArray[0];
}

public function getNewTextField(t:String, c:uint, s:uint):TextField {
if ((embeddedFont != null) && embeddedFont.hasGlyphs(t)) {
return getNewTextFieldEmbeddedFont(t, c, s)
}
else {
return getNewTextFieldDeviceFont(t, c, s)
}
}

public function getNewTextFieldEmbeddedFont(t:String, c:uint, s:uint):TextField {
trace("getNewTextFieldEmbeddedFont: "+t);

var tf:TextField = new TextField();
var fo:TextFormat = new TextFormat();

fo.font = embeddedFont.fontName;
fo.color = c;
fo.size = s
tf.defaultTextFormat = fo;
tf.autoSize = TextFieldAutoSize.LEFT
tf.type = TextFieldType.DYNAMIC;
tf.multiline = false;
tf.selectable = false;
tf.textColor = c;
tf.embedFonts = true;
tf.antiAliasType = AntiAliasType.ADVANCED;
tf.border = true;
tf.wordWrap = false;
tf.text = t;
return tf;
}

public function getNewTextFieldDeviceFont(t:String, c:uint, s:uint):TextField {
var tf:TextField = new TextField();
var fo:TextFormat = new TextFormat();

trace("getNewTextFieldDeviceFont: "+t);
fo.font = "_serif";
fo.color = c;
fo.size = s
tf.defaultTextFormat = fo;
tf.autoSize = TextFieldAutoSize.LEFT
tf.type = TextFieldType.DYNAMIC;
tf.multiline = false;
tf.selectable = false;
tf.textColor = c;
tf.embedFonts = false;
tf.border = true;
tf.wordWrap = false;
tf.text = t;
return tf;
}

}
}

Set the document class to Test and save all files. Pulish and run the movie and you will see the words "Bingo!" set with the embedded font.