Automate font compiling for Flex with Ruby

I came up with this solution when I had to compile over 100 fonts into SWF files for a recent project. Doing this by hand would have been madness so I wrote a ruby script and a shell script to automate the process.

Step 1: Setup

The directory structure I used was as follows.

convert.rb (the ruby script)
compile.sh (the shell script)
fonts/ (a directory for font files - .ttf and .otf)
as/ (a directory for the generated ActionScript)
swfs/ (a directory for the compiled swf files)

Step 2: Prep fonts

Ok told a tiny white lie when I said it was all automated. Since (to my knowledge) you can’t inspect a font file to determine if it’s normal, regular, bold, italic, or bold italic (the weights and styles Flex understands) you’ll have to set up a naming convention that the Ruby script can parse. You’ll be using the font name to create an ActionScript class so it should also be a legal name.

Here’s an example using the Arial family.

Arial.ttf (regular fontWeight and normal fontStyle)
Arial_Italic.ttf (regular fontWeight and italic fontStyle)
Arial_Bold.ttf (bold fontWeight and normal fontStyle)
Arial_BoldItalic.ttf (bold fontWeight and italic fontStyle)

Step 3: The Ruby Script

require 'find'

# delete any previous as
Find.find( 'as' ) do | as |
  if File.extname( as ) == ".as"
    File.unlink as
  end
end

# generate new as
Find.find( 'fonts' ) do | font |
  if File.file?( font )
    # extension name
    ext = File.extname( font )
    # is font
    if ext == ".ttf" || ext == ".otf"
      # file name
      full_name = File.basename( font )
      name = File.basename( font, ext )
      # font weight and style
      font_weight = ""
      font_style = ""
      if full_name.include? "_Bold" + ext
        font_weight = "fontWeight='bold',"
      end
      if full_name.include? "_Italic" + ext
        font_style = "fontStyle='italic',"
      end
      if full_name.include? "_BoldItalic" + ext
        font_weight = "fontWeight='bold',"
        font_style = "fontStyle='italic',"
      end
      # generate as
      f = File.new("as/#{name}.as",  "w+")
      f.write "package
      {
        import flash.display.Sprite;

        public class #{name} extends Sprite
        {
          [Embed(source='../fonts/#{full_name}', fontName='#{name}', #{font_weight} #{font_style} unicodeRange='U+0000-U+00FF,U+2100-U+214F')]
          public var Font:Class;
        }
      }"
      # some helpful output
      print ',"', "#{name}", '"'
    end
  end
end

In TextMate you can open this script and hit Command-R to run it, or run it via the command line ‘ruby convert.rb’. Once the script runs you’ll have generated ActionScript files in the ‘as’ directory ready to be compiled.

Step 4: The Shell Script

echo "<h2>Fonts Custom Compile</h2>";
echo "<code> Started @ `date "+%H:%M:%S"`</code><br />";

for i in `cd as/; ls *.as`; do
  swf=`echo $i |  awk -F. '{print $1}'`
  swf="$swf.swf"
  "/Applications/Adobe Flex Builder 3/sdks/3.3.0.4589/bin/mxmlc" -file-specs="as/$i" -o="swfs/$swf" -managers="flash.fonts.AFEFontManager" 2>&1;
done

You’ll need to customize the script for your Flex SDK location, mine is at "/Applications/Adobe Flex Builder 3/sdks/3.3.0.4589/bin/mxmlc". The hidden gem in there is -managers="flash.fonts.AFEFontManager", about 90% of fonts will compile without it but the rest were blowing up until I added that argument.

Again with TextMate you can run the script with Command-R. Each font will take about five seconds to compile, my set of over 100 fonts took over ten minutes :)

That’s it! The SWFs are compiled and ready to be runtime loaded into a Flex app. Creating the ActionScript for 100+ fonts would have been a multi-day process but with a little scripting it took less than an hour.

This entry was posted in ActionScript, Flex, Ruby. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

One Comment

  1. cmate
    Posted January 6, 2010 at 4:29 am | Permalink

    Just FYI – your actionsnip site is not working, there is an error when trying to view any of the snips.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word