AS3 Runtime Font Loading

Here’s a little experiment with loading fonts dynamically at runtime. So what’s this good for? Well let’s say you have a flash application where you want to allow users to customize the text formatting for some text box. Typically you would provide a small set of fonts which would all get embedded into the swf but this isn’t very flexible or ideal. Changing font’s or adding new one’s require rebuilding the swf. Also if only one or two fonts get used then all the other extra fonts do nothing but bloat the swf size. For this situation, it would be ideal to externalize the fonts and only load in the one’s needed.

Flash never supported this feature but some developer’s found ways around it. In particular, there was Shared Fonts Manager. However the author’s approach, although very impressive and useful, was a hack and not the easiest to use. With the major changes in flash 9, I got curious if runtime font loading was easier to do now and fortunately it is.

Approach

This isn’t new or anything, apparently all assets embedded in a swf become associated with a class and the ApplicationDomain object is the way to access classes in other swfs. The Flex documentation describes these topics but here, the focus is on fonts.

So first off, create the external font asset swf with something like the following:

package {

	import flash.display.Sprite;

	public class FontLibrary extends Sprite {

		[Embed(systemFont='Bank Gothic', fontName='emBank Gothic', mimeType='application/x-font')]
		public static var BankGothicFont:Class;

	}

}

Keep track of the class names you use and the fontName attribute of the Embed statement as that will be font name you’ll have to use in a text format. You can embed as many fonts within the swf as you like. I won’t describe the other features of the embed statement as they have been pretty well covered elsewhere.

After the swf is built (for this example let’s call it fontlibrary.swf), you load it like any normal swf via a flash.display.Loader object. After it is loaded, you just need to register the font class associated with the embedded font. Here’s an example of loading and registering the font library swf from above.

var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
loader.load(new URLRequest("fontlibrary.swf"));

private function completeHandler(event:Event):void {
	var FontLibrary:Class = event.target.applicationDomain.getDefinition("FontLibrary") as Class;
	Font.registerFont(FontLibrary.BankGothicFont);
	var tf:TextField = new TextField();
	tf.defaultTextFormat = new TextFormat("emBank Gothic", 12, 0);
	tf.embedFonts = true;
	tf.rotation = 15; // to demonstrate the embed worked
	tf.text = "blah blah blahnblah blah blahnblah blah blah ";
	addChild(tf);
}

If you’d like to grab a little demo with source, here’s a download.

More Thoughts

Another approach for the font asset swfs is to keep the main application class empty and include specific font classes thru the -source-path and -includes compiler options. A font class would then look something like this:

package {

	import flash.text.Font;

	[Embed(systemFont='Bank Gothic', fontName='emBank Gothic', mimeType='application/x-font')]
	public class BankGothicNormalFont extends Font {}

}

With this it won’t matter what the definition name of the main application class is (which was “FontLibrary” in the earlier example) or would you need to know the name of the static property associated with the font, you would just register the included font class such as “BankGothicNormalFont”. I prefer this approach better because of this and that it gives a little more control over to my build scripts. Say you want a font swf to contain more than one font, with the first approach you’ll need to edit the main application class to add the embeds but here you can just edit your build script to include the other font classes (assuming they’re already written).

Another thought was using the component compiler (compc). With compc you can embed non-source files directly however I have not tried it with fonts. It doesn’t seem like it gives you controls over the font style, weight, or other attributes available with the embed syntax. I played with some other options but none seem that great.

There are also runtime shared libraries (RSL) and modules with 2.0.1. I haven’t used them so if I’m wrong please let me know but from my understanding, RSLs do externalize assets and load at runtime however they are loaded when the swf loads. There is no control in actionscript for the loading of RSLs it appears. As for modules, I’m guessing they would be the better approach but not sure what advantages they offer over just using the ApplicationDomain object. Perhaps it has some management features I dunno. I can see a problem when loading and registering the same font swf twice. Well I’ll have to look into using modules.

3 Trackbacks

  1. [...] Our friend sent me a link to a nice article about loading fonts into the SWF file. It’s quite useful feature if you often use multiple SWF files in your sites or applications. Check it out. [...]

  2. [...] are a lot of real slick examples out there that use the Embed metadata to embed the font directly from the font file. This [...]

  3. [...] nochump.com » Blog Archive » AS3 Runtime Font Loading [...]

27 Comments

  1. Andres

    hi very interesting ur solution i was just wondering if this can be also achieved using flash 9 IDE, i have tried several ways but no luck, flash returns several errors

    Posted April 2, 2007 at 8:31 pm | Permalink
  2. I haven’t tried out the flash 9 alpha as3 preview actually…just been using the flex 2 sdk. I’ll go download it in a bit, you got me curious.

    Posted April 2, 2007 at 9:30 pm | Permalink
  3. Andres

    Good! hope not to be very lost then lol

    Posted April 3, 2007 at 7:02 pm | Permalink
  4. Well, I spent quite a bit of time on this today and unfortunately no luck :(

    The [embed(...)] syntax doesn’t work at all in the 9 preview which I’m sure you already discovered.

    So next I tried adding a font to the library set for export with a linkage class and interestingly enough, it’ll auto-generate a class if it doesn’t find one in the source path. Well, either way the loading app could not find the class definition giving an error…

    ReferenceError: Error #1065: Variable CustomFontClass is not defined.
    at flash.system::ApplicationDomain/getDefinition()

    I’m guessing you tried this too and was referring the same error.

    Well, I’m guessing the 9 preview compilation doesn’t make use of all the flex sdk tools. When embedding assets under the flex sdk, a separate java app pops up (i think flesxbuilder hides it tho) to handle those tasks. Since the [embed()] syntax is ignored by the 9 preview, I’m assuming…err guessing…that the class definition is not compatible with as3. The as3 documentation on LoaderContext.applicationDomain (http://livedocs.adobe.com/labs/as3preview/langref/flash/system/LoaderContext.html) mentions…

    “Use this property only when loading a SWF file written in ActionScript 3.0 (not an image or a SWF file written in ActionScript 1.0 or ActionScript 2.0).”

    So perhaps the 9 preview still exports assets under the as1 class definition? But if this is the case, this should change with flash cs3. Just caught this post today (http://blog.wrench.com.au/2007/04/03/flash-cs3-compiler/) pointing out in Adobe’s intro article that it will use the same compilers as flex builder which is just the sdk. Gotta figure the 9 preview does also but maybe just for as3 compiling and nothing else.

    Well for now, it looks you’ll need to use flex sdk/builder to create the external asset swfs but at least your main app can still be made thru the 9 preview.

    Posted April 3, 2007 at 10:27 pm | Permalink
  5. Jim Kremens

    Hi David,

    Nice! This works really well. But I’m running into problems down the road that I’m sure other people will face as well. (The documentation on Embed tags is pretty scarce…)

    I’m not clear on how you can include multiple fontWeights in one embed tag. The old AS2 trick was to put multiple textfields on the stage – one with each fontWeight you desired – and then compile that into a swf. Once you did that, you could use those different weights in your html text.

    I’m looking to do the same in AS3 – not Flex…

    Any ideas?

    Jim Kremens

    Posted June 18, 2007 at 5:20 pm | Permalink
  6. Jim Kremens

    This might make what I’m saying a little clearer. You can do the following with Flex:

    .myPlainStyle {
    fontFamily: “Myriad Web Pro”;
    fontSize: 24;
    }
    .myItalicStyle {
    fontFamily: “Myriad Web Pro”;
    fontSize: 24;
    fontStyle: italic;
    }
    .myBoldStyle {
    fontFamily: “Myriad Web Pro”;
    fontSize: 24;
    fontWeight: bold;
    }

    Is that possible using normal Embed statements?

    Posted June 18, 2007 at 5:39 pm | Permalink
  7. Jim Kremens

    Ok, here’s a much simpler question.

    When I compile your FontLibrary class above using Flexbuilder, the resulting swf is 52K.

    But in your download package, you’ve used Ant to compile the same class, and the swf is 20K.

    I’ve got all this working, but for some reason, the swfs produced are larger than they should be…

    Jim Kremens

    Posted June 19, 2007 at 2:06 am | Permalink
  8. Thanks Jim,

    So as for the font weights/styles, the embed tag does seem to support these. Indeed embed info is scarce, the most examples I could find are here. I tested with fontWeight and fontStyle and it compiled ok (tho I got an error saying the font alias wasn’t found when specifying both together).

    With flexbuilder compiling to 52k, are you sure you’re building an actionscript only project? My guess is it’s compiling in some of the Flex framework but could be wrong. I just did a build under the flexbuilder 3 beta and got 20k.

    Hope this helps some :)

    Dave

    Posted June 19, 2007 at 10:22 am | Permalink
  9. Jim Kremens

    “With flexbuilder compiling to 52k, are you sure you’re building an actionscript only project? My guess is it’s compiling in some of the Flex framework but could be wrong. I just did a build under the flexbuilder 3 beta and got 20k.”

    I’ve made an actionscript project and compiled the class as a main class. Shouldn’t be any Flex code in there. Very strange…

    I’m going to switch to Ant for builds anyway. Hope that will fix the problem.

    Jim

    Posted June 22, 2007 at 11:32 am | Permalink
  10. Hi Jim,

    if you’re looking for an AS3 / Flash CS3 solution, take at look at: http://www.betriebsraum.de/blog/2007/06/22/runtime-font-loading-with-as3-flash-cs3-not-flex/

    Posted June 23, 2007 at 6:03 am | Permalink
  11. Chris

    Hello Mr Dchang
    long time lol

    anyway … i am loading fonts into an as3 file using the following

    (Create a swf representing the font “_Arial.swf”)

    —————-code snip———————-
    [Embed(source='C:/WINDOWS/Fonts/arial.TTF',fontFamily="Arial")]
    public static var _Arial:Class;

    Font.registerFont(_Arial);
    ———————code snip—————-

    (then i load the font.swf into another swf when it is needed.)
    ——————–
    var loader:Loader = new Loader(); loader.contentLoaderInfo.addEventListener(Event.INIT,fontLoaded);
    loader.load(new URLRequest(“_Arial.swf”));
    —————

    i donot want to have to go through my system creating 100 swf files for fonts, + i want to be able to offer my users the ability to upload their own true type fonts.

    i want to be able to dynamicaly embed the fonts with a variable path and variable name .

    is it even possible to pass a var for the path / fontfamily of the embed syntax ?

    example:

    [Embed(source='{src}',fontFamily="{font}")]
    var _font:Class;
    Font.registerFont(_font);

    let me know your thoughts…. thanks

    Posted October 9, 2007 at 6:59 pm | Permalink
  12. 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.

    Posted October 13, 2007 at 3:01 am | Permalink
  13. Folks, how do you embed OTF fonts correctly by using an SWF file for the Flex compiler?

    I need to embed some OTF fonts into a Flash AS3 project that is compiled with the Flex2 compiler. The thing is: it will not work.

    I prepare a SWF in which I embed the fonts by putting them on the stage, check embed and set antialias for readability. Then I publish this SWF file.
    Then in my AS3 class I try to embed the SWF with e.g….

    [Embed(source='../assets/fonts.swf',
    fontName='Frutiger')]
    private static var FontClass:Class;

    The fonts are obviously embedded because the SWF is about 20kb larger but the TextFields don’t show any text. I have to use a StyleSheet object there and of course I have embed = true.

    Anyone know how to do this correctly?

    Posted November 4, 2007 at 3:42 am | Permalink
  14. Sascha
    I’ve been coming across a similar issue, though I’m skinning a completely different cat. I’m building an AS3 project that loads font libraries for different languages – works just fine to compile the font libraries in the Flash IDE if you need all the characters in a font, but not so if you don’t (say an Asian language). So, I built a middleware AS3 only project to embed the fonts I’ve embedded in Flash and the wrap them in a class. They need to be in a class, so I can use Font.registerFonts(). For some reason, when I load my externalFont.swf, registerFonts can’t find the classes – I get a “ReferenceError: Error #1065: Variable x is not defined.” Long story short, if I call Font.registerFont in the externalFont.swf main class, everything works fine. I never have to re-register my fonts in the main.swf. Not sure if this will help, or maybe adds another piece to a growing puzzle.

    Posted November 13, 2007 at 12:31 pm | Permalink
  15. Bogdan Petrea

    Hello all, especially Chris.
    You wanted to dynamically embed fonts into your application.
    My idea for you would be to use the FLEX module for apache or IIS to dynamically create swfs and generate the mxml files via a php script that writes to disk the mxml for each font.
    Hope this will work for you,
    Cheers.

    Posted December 13, 2007 at 12:09 pm | Permalink
  16. @ dchang:
    Very nice topic and helpful solutions, thanks!
    Now, I’ve been working on the problem myself for a while because I was used to creating shared font libs in the IDE.
    However, when creating a font lib using the Flex SDK as you suggest, would it not be easier to directly register the fonts in the constructor of the FontLibrary?

    That way you wouldn’t need to care about getting definitions and fishing for included font classes you might not even know the class names of (maybe someone else created the font class and didn’t document it properly :) ). Moreover, your application wouldn’t even need to know a thing about the fonts if the style definitions were included in an external style sheet that was loaded and applied as well.
    Voilà, no more font mess in the application: you load the lib, you load the style sheet and you create textfields and apply styles without knowing anything about fonts. :)

    @ danny:
    if you add a linkage to your font in the IDE (e.g. “AssetFont”) you do can register that font in your application without having to define an extra Main.as for your lib FLA.
    After having loaded the lib into your application as suggested in the above code use the getDefinition() approach to get your fonts definition via the font’s linkage you applied in the IDE:

    Example (font’s linkage is “AssetFont”):

    // dchangs loader code goes here …

    private function completeHandler(event:Event):void {
    var tSender : LoaderInfo = LoaderInfo(event.target);
    var AssetFont : Class = tSender.applicationDomain.getDefinition(“AssetFont”) as Class;
    Font.registerFont(AssetFont);

    // use font from here on…
    }

    Posted January 16, 2008 at 10:28 am | Permalink
  17. Here is a system to embed fonts WITHOUT using swf

    http://blog.paoloiulita.it/2008/03/11/as3-embedding-font-with-code-only/

    hope you like

    enjoy!

    Posted March 12, 2008 at 5:46 am | Permalink
  18. manotosh

    Hi I am facing trouble with font in my project, it is a hybrid of flash and flex project. I have the font embeded in main swf file and then loading flex compiled code swf file in my application… but the moment I run the main swf using flex compiled code any text using embed fonts as true does not show up. I even tried to enumerate the available embeded font in the swf but shows none… but when I compile the same code using flash and load it every thing works fine. Does anybody know why Flex As3 project exported swf file removes the font information from the main swf file?

    Posted June 11, 2008 at 12:11 pm | Permalink
  19. LdBl5s wrerrerreteee

    Posted August 5, 2008 at 9:57 am | Permalink
  20. Neil

    That so cool , I am come from Taiwan, I use this method to try Chinese Font, like this「文鼎中黑」,that can download from here–>http://bnseobto.googlepages.com/hei01mp.ttf ,but i am fail,oh~~no ~~~,I can’t embed any fons successful,but English wil…Orz. I can’t sleep will a long day.

    so… how can I do.

    thank you.

    Posted February 16, 2009 at 5:14 am | Permalink
  21. What can I say – I’ve tried so many ways for dynamically loading fonts, but your way is the single most simple and elegant way I’ve used so far.

    You can also use this approach if you want your Fonts Library to be a Resource Shared Library.

    The only question left to be answered is how to specify Unicode ranges?

    Any ideas on that?

    Posted March 10, 2009 at 10:22 am | Permalink
  22. hey! really nice idea, but for me it does not work with eclipse/as3 project.

    i’m getting an
    ReferenceError: Error #1065: Variable FontLibrary is not defined.

    for the line:
    var FontLibrary:Class = event.target.applicationDomain.getDefinition(“FontLibrary”) as Class;

    i, however, found a solution:
    var FontLibrary:Class = event.target.applicationDomain.getDefinition(getQualifiedClassName(event.target.content)) as Class;

    cheers! : )

    Posted September 24, 2009 at 6:42 pm | Permalink
  23. this is about the best method of font embedding using runtime loaded swfs I’ve seen.

    Just one question, how do I embed the bold, italic, and bold-italic versions of the same font?

    All inside different swfs?

    Posted October 2, 2009 at 9:51 am | Permalink
  24. Here is an experiment I’ve made that loads True Type Fonts at runtime.

    http://www.lucaslorentz.com.br/2009/11/loading-true-type-fonts-in-flash-at.html

    It’s also an option!

    Posted November 29, 2009 at 8:23 pm | Permalink
  25. Anubhav Soni

    thanks a lot, that was a great
    example….. :)

    Posted December 7, 2009 at 9:36 am | Permalink
  26. Hi All,

    I’ve tried this in Flash IDE and AS3; instead of doing a registerFont() for the class FontLibrary.SomeFont, I registered the loaded font class directly (SomeFont). It worked, except there is a bug that I can’t see to solve: when I have a textfield using the dyanmically loaded font and load it with text, it will not return it’s proper width and height via actionscript — it just returns the number 4 regardless of how much text is in it.

    Posted April 7, 2010 at 10:59 am | Permalink
  27. Very nice topic and helpful solutions, thanks!
    Now, I’ve been working on the problem myself for a while because I was used to creating shared font libs in the IDE.
    However, when creating a font lib using the Flex SDK as you suggest, would it not be easier to directly register the fonts in the constructor of the FontLibrary?

    Posted May 13, 2010 at 6:15 am | Permalink