Adding fonts to your SWF with FAMES

Carlos Rovira, author of the excellent Towards Open Source Flash Development, posted a question today on the MTASC mailing list: "Today a collegue asked me how to rotate some text using only OS tools. To rotate text he must embed the font and to do this he must use the Flash IDE... so I responded that he must use Flash IDE to do this task . . . Do you know some alternative method to insert fonts without the need of Flash IDE?"

Yessir, FAMES to the rescue!

Although my previous post on FAMES didn't make use of it, Swfmill allows you to add fonts to your SWF's library. You do this using the FONT tag in the simple dialect of SWFML. Here's an example:

1. Create a new project in Eclipse, call it Swfmill Font Test.

2. Create your SWFML file, FontTest.xml:

XML:
  1. <?xml version="1.0" encoding="iso-8859-1"?>
  2. <movie width="200" height="70" framerate="30">
  3. <background color="#ffffff"/>
  4. <frame>
  5. <font
  6. id="kharon"
  7. import="library/kharon.ttf"
  8. glyphs="Helo,Wrd!"
  9. />
  10. </frame>
  11. </movie>

Note how you can specify only the glyphs you want to use to be embedded.

3. Compile your skeleton swf from the command line, using:

swfmill simple FontTest.xml FontTest.swf

4. Create a new ActionScript file called FontTest.as:

ActionScript:
  1. class FontTest extends MovieClip
  2. {
  3. var tfMessage:TextField;
  4. var sW:Number = null; // Stage width
  5. var sH:Number = null; // Stage height
  6. private function FontTest ( target )
  7. {
  8. // Assimilate the target
  9. target.__proto__ = this.__proto__;
  10. target.__constructor__ = FontTest;
  11. this = target;
  12.  
  13. Flashout.log ("Application initialized: " + this );
  14. // Store stage dimensions for easy look-up
  15. sW = Stage.width - 1;
  16. sH = Stage.height - 1;
  17. // Draw border around the stage
  18. lineStyle ( 1, 0x000000 );
  19. moveTo ( 0, 0 );
  20. lineTo ( sW, 0 );
  21. lineTo ( sW, sH );
  22. lineTo ( 0, sH );
  23. lineTo ( 0, 0 );
  24. //
  25. // Create message
  26. //
  27. var CORRECTION_FACTOR = 1.40; // getTextExtent workaround
  28. var messageTextFormat = new TextFormat();
  29. messageTextFormat.size = 8;
  30. messageTextFormat.font = "kharon";
  31. var messageText:String = "Hello, World!";
  32. var messageTextExtent:Object = messageTextFormat.getTextExtent ( messageText );
  33. var messageWidth:Number = messageTextExtent.textFieldWidth * CORRECTION_FACTOR;
  34. var messageHeight:Number = messageTextExtent.textFieldHeight * CORRECTION_FACTOR;
  35. var messageX = sW / 2 - messageWidth / 2;
  36. var messageY = sH / 2 - messageHeight / 2;
  37. createTextField( "tfMessage", 10000, messageX, messageY, messageWidth, messageHeight );
  38. // Write message text
  39. tfMessage.embedFonts = true;
  40. tfMessage.text = messageText;
  41. // tfMessage.border = true; // used to debug getTextExtent
  42. tfMessage.setTextFormat ( messageTextFormat );
  43. }
  44. static function main ()
  45. {
  46. // Create a FontTest instance and
  47. // have is assimilate _root.
  48. var test:FontTest = new FontTest( _root );
  49. }
  50. }

Note how we specify the font name ("kharon") based on the id in our SWFML file. Also note that I had to massage the results getTextExtent() was giving me (if you turn the textfield's border on remove the correction, you'll see why.)

5. Create your Flashout file, FontTest.flashout and set your SWF and root class.

6. Compile to run! You should see the SWF below, using the Kharon4a pixel font by orgdot.

Note: I noticed that Flashout doesn't display the resulting SWF correctly. See snapshow below:

Flashout render bug

Download the example files (22kb)

[Update] George (from Square Circle) just emailed me to let me know that the text field doesn't completely display on a Mac. Oh gotta love getTextExtent() :) Just alter the CORRECTION_FACTOR constant (raise it) if you get the same issue.

I tried using getTextExtent2() but that didn't work. Actually, mx.core.ext.UIObjectExtensions wouldn't run under MTASC. It gave an annoying Local variable redefinition error due to the way the class is coded. That's one compiler error I'm not too fond of (and usually I just love the critters) as it's very convenient to use local vars like i, etc. all over the place and I actually *do* want to think of them as different variables each time I use them.)

Comments