Dynamically loading fonts with FontLoader and applying styles with CSS stylesheet in Actionscript 3.0

by Rafael Nuenlist 29 views11

You are going to learn, how to easily load fonts apply a css stylesheet to a textfield. Until now, it has always been a big mess dynamicaly loading fonts. With the new fontloader from etcs.ru the process got easy as pie. All you need to do is to create a flash file, add dynamic textfields with the fonts you want and change the font weight and/or style to your needs. Then you just need to publish the swf and load it with the fontloader. What the fontloader does is reading the swf bytecode and extract all fonts from it and registers it to the flash font class. The rest is just normally loading the css file and apply it to a textfield. So, let’s get this started!

Requirements

Create the Flash file with fonts

In this tutorial, we’re going to show you how to use multiple fonts. Let’s say you have a textfield that needs to be able to display normal English glyphs, Japanese kanjis and Russian glyphs. In that case, we’re going to embed 3 different fonts since not every font can display all the glyphs. For the English characters, we’re using Verdana (not bold, not italic), for the Russian glyphs we’re embedding the font Times New Roman CYR (not bold, italic) and for the Japanese kanjis we’re including Arial Unicode MS. Then we just compile it and put it in the folder “resources/”.
If you want to embed a bitmap font, then make sure, you select the appropriate font size to get it sharp and not anti aliased.

Create the CSS file

The CSS file helps us to handle all the styles like in traditional HTML websites. Like this you can completely forget about the TextFormat class from flash since AS3 CSS supports these settings too. You can get all the supported CSS properties from the Livedocs. In our case, we need 3 new CSS classes, one for each glyph type:

.cyrillic {
	font-family:	"Times New Roman CYR";
	font-size:		15;
	color:		#CCCC33;
}

.japanese {
	font-family:	"Arial Unicode MS";
	font-size:		15;
	font-weight:	bold;
	color:		#CC3333;
}

.english {
	font-family:	"Verdana";
	font-size:		15;
	font-style:	italic;
	color:		#009966;
}

As you can see we took the exact same fonts settings from the Flash IDE. And here’s an important note: In some cases the font family name might differ from the one you see in the IDE, for example Times New Roman CYR can also convert to Times New Roman Cyr. So it is important to double check the font family with the font name loaded from the fontloader. But that’s no big deal since our dynamic font loader outputs all the loaded font’s settings.

Create dynamic font loader

As we said before, we’re going to use the fontloader class from etcs.ru. So what we do is creating a new Flash file (optionally adjust the background) and import all the flash internal classes and the font loader:

// import flash internal classes
import flash.events.Event;
import flash.events.HTTPStatusEvent;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLRequestMethod;
import flash.net.URLVariables;
import flash.text.Font;
import flash.text.StyleSheet;

// import font loader
import ru.etcs.utils.FontLoader;

Next we declare the variables for the CSS StyleSheet, the fontloader and the urlLoader for loading the css and swf file

var cssStyleSheet:StyleSheet;
var fontLoader:FontLoader;
var urlLoader:URLLoader;

Now we write our loadCSS function for loading the css stylesheet. First we instantate the URLLoader, then we add the event listeners for errors and notifications which we are going to look at later. And the last line instantiates a new URLRequest with the path to the css file and loads it with the URLLoader.

function loadCSS():void {
	urlLoader = new URLLoader();

	urlLoader.addEventListener(IOErrorEvent.IO_ERROR, handleIOError);
	urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, handleHttpStatus);
	urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handleSecurityError);

	urlLoader.addEventListener(ProgressEvent.PROGRESS, onProgress);
	urlLoader.addEventListener(Event.COMPLETE, onCSSComplete);

	urlLoader.load(new URLRequest("resources/style.css"));
}

Next we are defining our onCSSComplete function which will be called once the file is fully loaded. What this complete handler does is instantiating a new Stylesheet and parsing the received data. And finally it will call the function loadFonts with a URLRequest holding the path to the fonts swf file.

function onCSSComplete(e:Event):void {
	cssStyleSheet = new StyleSheet();

	cssStyleSheet.parseCSS(urlLoader.data);

	loadFonts(new URLRequest("resources/fonts.swf"));
}

Our loadFonts function will instantiate a new FontLoader. Since the FontLoader dispatches all the same events when loading the data, we can just simply use the same event listeners as for the URLLoader. And last of all, we tell the FontLoader to load the request defined in the function parameter.

function loadFonts(request:URLRequest):void {
	fontLoader = new FontLoader();

	fontLoader.addEventListener(IOErrorEvent.IO_ERROR, handleIOError);
	urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, handleHttpStatus);
	fontLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handleSecurityError);

	fontLoader.addEventListener(ProgressEvent.PROGRESS, onProgress);
	fontLoader.addEventListener(Event.COMPLETE, fontsLoaded);

	fontLoader.load(request);
}

Once the FontLoader has loaded and registered the fonts, the fontsLoaded function gets called. What it does is looping through each loaded font and output its fontstyle/fontweight and the font name. This will help you to make sure that you’ve entered the right font-family in the CSS file. So if your textfield would be empty even if you’ve added text to it, make sure you check the fontname. After the output sequence, we launch the displayCSSTextField function.

function fontsLoaded(e:Event):void {
  var _arrFonts:Array = fontLoader.fonts;
  for each (var _font:Font in _arrFonts) {
  var _isBold:Boolean	= false;
  var _isItalic:Boolean	= false;
  switch (_font.fontStyle) {
  case FontStyle.BOLD:
  _isBold = true;
  break;
  case FontStyle.BOLD_ITALIC:
  _isBold	= true;
  _isItalic	= true;
  break;
  case FontStyle.ITALIC:
  _isItalic = true;
  break;
  }
  trace("************ Loaded Font ***************");
  trace("  Font Name:   " + _font.fontName);
  trace("  Font Bold:   " + _isBold);
  trace("  Font Italic: " + _isItalic);
  trace("****************************************");
  }
	displayCSSTextField();
}

To display out fonts, we will create a new textfield. Then we center it to the stage with a margin of 25px. Next we turn on embedFonts to tell the textfield to use the embed fonts. After that we allow the textfield to use more than a single line of with multiline turned on. Next step is to set the autoSize to LEFT just in case our textfield should grow higher than the initial height. Now the important part is to assign the stylesheet to the textfield. This is done pretty straightforward, just assign our cssStyleSheet Variable to the styleSheet property of the textfield. Then we add some text to it, in our case there’s 3 <span> with our 3 defined stylesheet classes and some random text in English, Japanese and Russian. Last of all we add the textfield to the display list.

function displayCSSTextField():void {
  var _textField:TextField = new TextField();

  _textField.width	 = stage.stageWidth - 50;
  _textField.height = stage.stageHeight - 50;
  _textField.x = 25;
  _textField.y = 25;

  _textField.embedFonts = true;

  _textField.multiline	= true;

  _textField.autoSize	= TextFieldAutoSize.LEFT;

  _textField.wordWrap	= true;

  _textField.styleSheet	= cssStyleSheet;

  _textField.htmlText = "<span class='english'>Lorem ipsum ius et dico soleat ancillae, eos ei falli noluisse dissentias. Ad pri fugit delicata, quo dicam impetus euismod ut. Ut novum possim elaboraret vix, cu eam kasd atqui novum, vero nostrud sententiae an per. Mel ad commune takimata, pri<br/><br/><br/></span>";

  _textField.htmlText += "<span class='japanese'>ティのい アクセシビ オサリングツ ロジ セシビ, 功久 わった びつける プロトコル を始めてみよう ンテ と会意味 セシビリティ とセマンティック 内准剛, わった のな レイテリング とセマンティック ユザエ 丸山亮仕 およびそのマ まきかずひこ の徴, 寛会 プロセスド サイト作成のヒント ウェブコ わった, ンテ クセス オブジェク ビスとレイティ クセシビリティ ネッ オサリングツ ビスとレイティ ラベラ, 拡なマ のな スタイル びつ<br/><br/><br/></span>";

  _textField.htmlText += "<span class='cyrillic'>Алексей Федорович Карамазов был он не думаю. Вот и сверх того, в котором даже хотел выставляться. Может, по первому даже существ женского пола, а только эта плита оказалась в другой губернии, в ней теплилась лампадка. Около нее тогда называли, хотя он вовсе ему</span>";

  addChild(_textField)
  }

To start our dynamic font loader procedure, you’ve guessed, we call the function loadCSS

loadCSS()

Here is the final result.

Dynamic Font Loader Tutorial - Final Result

We’ve already reached the end of the tutorial. We hope that you enjoyed reading it and we appreciate any kind of feedback.

Comments (11)

  1. Thanks, great soloution for my current project, was looking for a good solution for japanese characters.. now I just have to find a solution for South Korean characters… Any ideas?

  2. @Pierre: I’m glad you can use it. For Korean characters you will need a font that supports these glyphs. After you’ve found one, I’d just play around with the “Korean Basic Hangul” and “Korean Hangul (All)” character sets. If the character sets don’t work out for you, then you might be interested in making a custom one -> http://www.psyked.co.uk/adobe/flash/custom-character-set-embedding-in-flash.htm
    Or you could just copy&paste the whole text in the “Include these characters:” input field.

  3. … Or you could just upload a textfile containing your content and get the xml with the unicode characters from here -> http://www.epic.dk/flash-unicodetable/flash-unicodetable-generator.php 😉

  4. Thanks for the reply, I will look this up 🙂

  5. Hi Rafael, i am having trouble with links in the html, embedded fonts and stylesheets. somehow the text is not rendered as expected in flash.

  6. Great article, I was wondering how I could add smoothing to the images because I am displaying them angled but when the images load they become distorted.

    Thank you

  7. @Sam: You can access the image by setting a id-attribute to the img tag. Like this:

    And for the AS3 Code:

    var ldr:Loader = textfield.getImageReference(“image”);
    ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);

    private function imageLoaded(e:Event):void
    {
    e.target.removeEventListener(Event.COMPLETE, imageLoaded);
    Bitmap(e.target.content).smoothing = true;
    }

    @bas: Could you upload a test FLA or post the code?

  8. Hi! EmbedFonts is driving me nuts. When embedFonts is set to true the font disappears, however when it’s not set it’s visible…

  9. Very smart ByteArray manipulation for assigning class name to embedded fonts. Really great!
    Keep it up.

    If you have any idea about iteration through ApplicationDomain, please share it.

    Thank you.

  10. Very impressive, I like your byte magic 😉

  11. Hi,

    Great tutorial! I was just wondering if this still works with Flash Player 10.1 or 10.2
    I’ve tried it and only the Japanese texts show up on screen.

    Thanks.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>