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.

4 comments:

Evgeny said...

All work for en lang.
But for ru lang I can't get working examle. Russian letters dissappear. Have any idea?

Santana said...

Yes, exactly the same thing. I found a pity comment saying "…For those of you using Flash IDE: font embedding in Flash CS3 doesn’t support special characters that are out of Latin 1 range (unicode). For further information please read an article at flash tekkie".

Feels like we'll have to use Flex to export these font SWFs.

Steve said...

Does this work with CSS Styles? I want to be able to do something where a sentence passed to the textfield could have individual elements wrapped in span's that have different classes.

Where one is a style from a stylesheet that specifies one font and another would be a class that specifies another font. Both being embedded with this method.

Know if that's possible?

CodingFather said...

There are some video tutorials on http://codervods.com about ActionScript fonts, I thought you might be interested.