Select Page

FontControl class – external font library

Loading fonts in dynamically in AS3 is so much better than AS2. If you want to have an external library of fonts that you only load as you need then this is the way to go. Create some SWF files that only contain the font combinations that you will need and then load them in to use using this FontManager class.

package com.sitedaniel.text
{
    import flash.display.Loader;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.EventDispatcher;
    import flash.net.URLRequest;
    import flash.system.ApplicationDomain;
    import flash.text.Font;

    public class FontControl extends EventDispatcher
    {
        public static  const COMPLETE:String = "font_load_complete";
        public static  const ERROR:String = "font_load_error";
        public static  var FONTS:Array;

        private var _loader:Loader;
        private var _domain:ApplicationDomain;

        public function FontControl() {
        }
        public function load(path:String, fontArr:Array):void
        {
            FONTS = fontArr;
            _loader = new Loader();
            _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, _ioErrHdlr);
            _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, _loadComplete);
            _loader.load(new URLRequest(path));
        }

        private function _loadComplete(e:Event):void
        {
            _domain = _loader.contentLoaderInfo.applicationDomain;
            _registerFonts();
            var embeddedFonts:Array = Font.enumerateFonts(false);
        }

        private function _registerFonts():void
        {
            for (var i:uint = 0; FONTS[i]; i++)
            {
                Font.registerFont(_domain.getDefinition(FONTS[i].id) as Class);
            }
            dispatchEvent(new Event(COMPLETE));
        }

        private function _ioErrHdlr(e:IOErrorEvent):void
        {
            trace(e);
            dispatchEvent(new Event(ERROR));
        }
    }
}

Using this font control you can have multiple libraries of fonts that you choose to load at runtime. Generally the library you load is determined by the language and character support that you need. When you call _fontControl.load(…) you can have a switch statement to load in and register different fonts for each language that you need. Of course you need these font SWF files set up correctly. In ‘font_hei.swf’ that this example is loading in, there are two fonts set up to export with the linkage IDs of ‘FontHei’ and ‘FontMain’. These fonts are ‘AdiHaus Bold’ and ‘Hei’ respectively. ‘Hei’ is a Chinese font and about 3M in size. There is no way I want to load this font if I don’t have to.

Then when you create your FontLoader instance, you pass in the path and an object that reflects these font names and ids:

_fontControl = new FontControl();
_fontControl.addEventListener(FontControl.COMPLETE, _fontsLoaded);
_fontControl.load("swf/font_hei.swf", [{font:"AdiHaus Bold", id:"FontMain"},
                                         {font:"Hei", id:"FontHei"}]);

The ‘FontMain’ actual font name is ‘AdiHaus Bold’.

Then when you want some dynamic text, you can either use the font name that you’ve just loaded, ‘AdiHaus Bold’

var tf:TextField = new TextField();
var fmt:TextFormat = new TextFormat('AdiHaus Bold', 30, 0x000000);
tf.autoSize	 = TextFieldAutoSize.LEFT;
tf.embedFonts = true;
tf.text = 'Lorem Ipsum...';
tf.setTextFormat(fmt);
this.addChild(tf);

or use a static variable reference in the font Manager, FontControl.FONTS[1].font

var fmt:TextFormat = new TextFormat(FontControl.FONTS[1].font, 30, 0x000000);

I prefer using this static var method as you can change the font of a complete site just by updating the library that loads in.

UPDATE: 6th Jan 2010 – removed unnecessary use of DynamicEvent class, now just standard Event class

Adidas coreskills scoreboard

I just finished this AS3.0 project which will be going into the flagship adidas stores in London, Beijing, Paris and other big cities. Basically in the store there are these tests you can take and if you register and enter your details then your scores are saved in a database. The top 5 men and women scores for each event and some other categories are then displayed instore. It is AS3.0 and XML driven. The dynamic font manager class I wrote for this will be up here soon.

Getting FlashVars from the URL – javascript function

Here’s a very handy javascript function to grab FlashVars from the URL. ‘GUP’ Get URL Parameters can sit in your html or in an external js file.

function gup(name){
    name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
    var regexS = "[\\?&]"+name+"=([^&#]*)";
    var regex = new RegExp( regexS );
    var results = regex.exec( window.location.href );
    if( results == null ) return "";
    else return results[1];
}

And then when you create your SWF object, pass in the value name you are looking for (in this case ‘page’)

var so = new SWFObject("loader.swf?page="+gup('page'), ...

Loading dynamically generated images in Binary

Recently I had to load in images from database references that were pointing to a .net serverside script. This path ended with something like ImageHandler.ashx?id=164
When I tried to load this in with my standard ImageLoader it didn’t work because it was coming back as binary and I was getting a reference error about the URL type not being found. I think it was
Error #2044: Unhandled IOErrorEvent:. text=Error #2124: Loaded file is an unknown type.
The way to get around this is a little strange and involves 2 loading processes. The first one loads in the data but set as

_loader.dataFormat = URLLoaderDataFormat.BINARY;

Then once this has loaded we ‘load’ the ByteArray that is returned into a loader and proceed as normal:

public function loadBinaryJPG(_path:String):void
{
	_loader = new URLLoader();
	_loader.addEventListener(Event.COMPLETE, _onLoadInit);
        // set the dataFormat to binary
	_loader.dataFormat = URLLoaderDataFormat.BINARY;
	_loader.load(new URLRequest(_path));
}

private function _onLoadInit(e:Event):void
{
	_loader.removeEventListener(Event.COMPLETE, _onLoadInit);
        // once the binary data has loaded, check that there
        // is data there and load that into a Loader
	var _l2:Loader = new Loader();
	_l2.contentLoaderInfo.addEventListener(Event.COMPLETE, _blComp);

	var _byteArr:ByteArray = new ByteArray();
	_byteArr = _loader.data;
	// check that data was returned
	if(_byteArr.length != 0)
	{
		_l2.loadBytes(_loader.data);
	} else {
		// generate error message
	}
}

private function _blComp(e:Event):void
{
        // deal with binary data that is in the loader (e.target)
	_bmdata = new BitmapData(114, 87, false, 0xFFFFFF);
	_bmdata = (e.target.content).bitmapData;

	_bm = new Bitmap(_bmdata, "auto", true);
	// deal with loaded Bitmap
}