Fast and Responsive Flash: Loading Fonts on Demand

When dealing with Flash, or any other web-based tool, you’ve got to try to keep the file size in check. Visitors only have so much patience and won’t be happy sitting around while a multi-megabyte SWF file slowly ticks away. To help speed things along without sacrificing rich content, I’ve been moving towards loading non-essential assets, such as fonts and images, on demand. Fonts, for example, can occupy as much as 100Kb per style, which can translate to several seconds of waiting on a slower internet connection. When the user can choose between several fonts and styles, it becomes unworkable to load all of them immediately. Flash, at least under AS2, doesn’t provide a native mechanism for loading and working with fonts embedded in an external movie. Fortunately, there’s a well-known hack that can bypass this (arbitrary?) limitation and let us load in fonts as and when they’re required. Here’s a quick overview of how it works:
  1. Embed the desired font into a dynamic text field in a new movie. Convert the text field to a symbol and export it for runtime sharing.
  2. Create an intermediate ‘loader’ movie. Add a placeholder symbol to the stage that imports the font symbol from the previous step.
  3. On the first frame of the intermediate movie, add a line of ActionScript to notify your host movie that the font has finished loading.
  4. Load the intermediate movie into your host movie and listen for the notification message. Once received, you’re free to use the new font however you like.
I’ve made my own improvement to the above technique, however, by moving the notification event out of the intermediate font movie and into an encapsulated FontLoader class within the host movie. The thorn here is that a normal onLoad event will ignore runtime-shared assets and can be fired before they’ve finished loading. To get around this, I set up an onEnterFrame listener to periodically check the bounds of the external movie. Assuming it contains nothing but a single shared asset, its width and height will be only be > 0 once the asset has loaded, at which point I broadcast the onLoad event myself. It’s also worth noting that conflicts can arise when loading fonts in this way. In particular, while using Arial as a GUI font pre-embedded in the host movie, I was unable to load a second copy without making a mess of static text. In my case, it was easy enough to pre-load the external version and use that alone, but you can’t always be so fortunate. I’d recommend not pulling the same font from multiple sources (including static text fields) or, if you can’t easily avoid it, at least build a quick test-case to make sure you won’t be wasting your time. Next time, I’ll be looking at some of the problems I’ve encountered with other, non-font assets and also talk about how to anticipate what can be loaded before it’s actually needed. Part 1: Introduction