Using fonts inside a runtime shared library (RSL) loaded trough actionscript in Flash CS4 and CS5

This post describes how to use fonts which are stored in a runtime shared library (RSL) that is loaded trough actionscript. The post continues from the previous post I made about loading RSL via actionscript.

As a start I created two flash files very similar to the other article:

  1. The first file acts as the RSL file. I added Font definition to the library; using Arial Regular. I checked the Export for runtime sharing, used ArialRegular as class name and entered for the URL the name of an empty SWF.
  2. Into a second file I copied and pasted the Font definition from the first file (which automatically turned on Import for runtime sharing. I extended the timeline to 10 frames, created a new keyframe at frame 5 and placed at that frame a dynamic text field with some text using the font from the library. I also placed stop() at frame 5.
    At frame 2 I added the following code:
    this.stop();
    var loader: Loader = new Loader();
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
    loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onError);
    var context: LoaderContext = new LoaderContext();
    context.applicationDomain = ApplicationDomain.currentDomain; 
    loader.load(new URLRequest('test.export.picture.swf'), context);
     
    function onComplete(anEvent: Event): void
    {
    	trace('loaded');
    	play();
    }
     
    function onError(anEvent: IOErrorEvent): void
    {
    	trace('error');
    }

    This code will load the RSL and then continues the movie.

As shown in the other post, the Font definition will be present in the main movies context. However after testing the movie, I did not see any text.
It turns out having the Font definition in the same context is not enough, the definition has also to be registered trough the static method Font.registerFont().

So I changed the code at frame 2 to:

...
function onComplete(anEvent: Event): void
{
	trace('loaded');
	Font.registerFont(ApplicationDomain.currentDomain.getDefinition('ArialRegular') as Class);
	play();
}
...

Now the text was showing up when testing the movie.

Summary
To use Font Definition stored into a RSL, it needs to be registered (after the RSL has been loaded into the same domain) trough the method Font.Font.registerFont().
To obtain the definition use the method ApplicationDomain.currentDomain.getDefinition().

Prototype and as3

On twitter someone asked something which included the prototype property. With as1 I used (like all) prototype to extend and create new classes. With as2 class definitions changed completely and since then I stopped using prototype. I never thought about it, until someone mentioned it on twitter.

I became a bit curious about the prototype property and what its function is within as3; so I did some tests.

It seems Flash looks in prototype property when it can not find a method or variable name within the class (and super classes) definition or instance (in case of dynamic classes). If the prototype property does not contain the method or variable name, Flash will look in the prototype property of the super class (and so on).

The prototype is the last place looked in; so any definition in the class or super class will always come first. Flash also searches first within methods and variables added to a dynamic class instance during run-time.

The only useful thing I could think of so far is the ability to extend existing dynamic classes with methods and variables (not real properties, since there does not seem to be a way to add getter and setter methods). This looked promising, since with as1 I extended several base classes to include additional methods (like the Array, String and Math class). With as2 this was not longer possible and I created static helper classes instead.

Example:

Array.prototype.randomItem = function(): *
{
  return this[Math.floor(Math.random() * this.length)];
};
 
var list: Array = ["Red", "Orange", "Yellow", "Purple"];
 
trace(list.randomItem());
trace(list.randomItem());
trace(list.randomItem());

I was also curious if there would be a difference in calling methods stored in prototype and calling methods of a class/instance. For this i created the following class:

package
{
  public dynamic class One extends Object
  {
    public function One()
    {
      One.prototype.testFunction2 = function()
      {
        var dummy: int = Math.floor(Math.random() * 1000);
      };
 
      One.prototype.testFunction3VeryLongNameAtLeastTwiceAsMuchCharacters = function()
      {
        var dummy: int = Math.floor(Math.random() * 1000);
      };
    }
 
    public function testFunction1()
    {
      var dummy: int = Math.floor(Math.random() * 1000);
    }
  }
}

And then executed the following from a dummy movie within the Flash IDE:

var starttime: int 
var cnt: int;
var one: One = new One();
starttime = getTimer();
for(cnt = 0; cnt < 1000000; cnt++)
{
  one.testFunction1();
}
trace("time: " + (getTimer() - starttime));
starttime = getTimer();
for(cnt = 0; cnt < 1000000; cnt++)
{
  one.testFunction2();
}
trace("time: " + (getTimer() - starttime));
starttime = getTimer();
for(cnt = 0; cnt < 1000000; cnt++)
{
  one.testFunction3VeryLongNameAtLeastTwiceAsMuchCharacters();
}
trace("time: " + (getTimer() - starttime));

As result it turned out that last two loops took almost the double time as the first loop. The last two loops were very similar in duration; so there seems not to be any influence of the length of the function name.

It looks like using prototype has some downsides:

  • Only dynamic classes can be extended, one can not add methods to Math for example.
  • Calls to methods stored in the prototype take longer to execute (see test below)
  • Since methods are added run-time, editors can not show them with code hinting or use the correct syntax highlighting

I’ll probably will never use the prototype property, but maybe someone finds a good use for it.