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 -includescompiler 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.

出处:http://nochump.com/blog/archives/20

 

posted on 2012-09-06 15:33  cria  阅读(292)  评论(0编辑  收藏  举报