divillysausages.com

AS3 Font embedding masterclass

One of the people I follow on Twitter, Jesse Freeman, twitted that he was having some problems getting embedded fonts working properly in Flash. As the problem sounded immediately familiar (the amount of time you spend cursing out something in Flash is inversly proportional to the amount of time it takes to remember what it was), I chimed in with what turned out to be the solution. Long story short, if you're having problems embedding fonts in AS3, try setting embedAsCFF = "false" in your embed code.

Simply finishing this post at that doesn't really satisfy my need to have mountains of text on the internet and thus look like I know what I'm talking about, so I figured to share the info I gathered up about a year ago when I hit the same problem. So why is embedded fonts in AS3 such a Pain In The Ass™ ?

There are 3 main ways to embed a font in a SWF:

Direct embedding

This is probably the most common for Flash game devs looking to embed a specific font for their game. For this, we're using the [Embed] metatag:

// to embed a font file that's relative to your project
[Embed(source="../someFont.ttf", 
	fontName = "myFont", 
	mimeType = "application/x-font", 
	fontWeight="normal", 
	fontStyle="normal", 
	unicodeRange="englishRange", 
	advancedAntiAliasing="true", 
	embedAsCFF="false")]
private var myEmbeddedFont:Class;

// to embed a system font
[Embed(systemFont="Arial", 
	fontName = "myFont", 
	mimeType = "application/x-font", 
	fontWeight="normal", 
	fontStyle="normal", 
	unicodeRange="englishRange", 
	advancedAntiAliasing="true", 
	embedAsCFF="false")]
private var myEmbeddedFont:Class;

It doesn't matter what you call the variable under the Embed tag as you don't use it. You also don't need all of these parameters, but I'll explain each one briefly.

Using an embedded font

To use this in your project, you first set up a TextFormat object with the font parameter set to the fontName that you specified in your Embed statement. Also make sure to specify embedFonts = true; on your TextField otherwise you won't use them/it won't show up. To easily know if your TextField is using the embedded fonts, just rotate your TextField slightly, as only embedded fonts can be rotated.

// create our TextFormat
var tf:TextFormat = new TextFormat( "myFont", 20 );

var t:TextField 	= new TextField;
t.embedFonts 		= true; // very important to set
t.autoSize 			= TextFieldAutoSize.LEFT;
t.defaultTextFormat = tf;
t.text 				= "Hello World";
this.addChild( t );

Embedding using a SWF

Embedding fonts using a SWF is somewhat easier. If you've ever created a game in Flash and used the Flash IDE to produce graphics, you've probably done everything you need to before.

Here, I've created two TextFields, one static and one dynamic. The static TextField is using the Futura Md font, while the dynamic TextField is using the Courier New font and embedded with the characters for Basic Latin.

Creating TextFields in Flash

If you're using FlashDevelop, then you can see what fonts are embedded in a SWF, including the number of characters:

Exploring the fonts in an external SWF in FlashDevelop

As you can see, there's two fonts available for me to use. There's only 11 characters for Futura Md, as that TextField was static, so Flash only includes the characters used.

For our AS code, we change the Embed call to:

[Embed(source="../assets/test.swf", fontName="Courier New" )]
private var myEmbeddedFont:Class;

Note that the fontName is the name of the font that you used in Flash. If you embedded a bold/italic version, then you'll also have to set fontWeight = "bold" or fontStyle = "italic".

NOTE: If you use a static TextField you MUST set it as selectable, otherwise you won't be able to access the font.

// create our TextFormat
var tf:TextFormat = new TextFormat( "Courier New", 20 );

// create the TextField the same as above

Embedding using a font symbol

Finally, we can embed fonts using a font symbol in Flash.

Here, I added a font symbol for the Times New Roman font and gave it an export linkage name of "myFontSymbol":

A font that was embedded through a font symbol

You'll notice that there's 243 characters in our font symbol. That's because there's no way (at least that I've found in CS3; it might be different in CS5) to say that you only want to export a specific set of glyphs.

In our AS code, we make a change to the Embed code like this:

[Embed(source="../assets/test.swf", symbol="myFontSymbol" )]
private var myEmbeddedFont:Class;

As we're embedding a symbol here, don't set the mimeType, fontStyle etc. or the compiler will throw an Error along the lines of Error: transcoding parameters 'symbol' and 'fontStyle' are incompatible. For the font property of your TextFormat object, we change it to the name of the font, not the font symbol name, or the symbol linkage name.

// create our TextFormat
var tf:TextFormat = new TextFormat( "Times New Roman", 20 );

// create the TextField the same as above

Problems

"My TextField fonts still look ugly, even though the font is embedded!"
Make sure you've set the TextField's embedFonts property to true. To make sure that you're using an embedded font, set the rotation property to a value other than 0, as only embedded fonts will show when the TextField is rotated.

"Flash says my font is embedded but I can't get it to work!"
When you're embedding your font, set embedAsCFF to false, or compile with -manager=flash.fonts.AFEFontManager to use the Adobe Font Manager, or compile with compatibility-version set to 3.0, where the default value for embedAsCFF is false.

"I get an 'unable to transcode' error!"
Check the embed path to your font. Make sure it's relative to the file that's doing the embedding, not your project root or the SWF file.

"I get a 'transcoding parameters 'x' and 'y' are incompatible' error!"
You're probably trying to embed a symbol and not a font. See the Embedding using a font symbol section.

"I get an 'unable to build font' error!"
Try using the Adobe Font Manager by compiling with -manager=flash.fonts.AFEFontManager.

"I get an 'invalid Unicode range 'ENGLISHRANGE'' error! (or similar)
If you're hardcore, and entering unicode ranges by hand, make sure it's actually valid. They should be in the form unicodeRange="U+0041-U+005A,U+0061-U+007A" (upper- and lower-case a-z) and you can find a list of the ranges online.
If you're using named ranges, make sure they're defined in the right config file (all found in PATH_TO_FLEX_SDK/frameworks): flex-config.xml for AS3/Flex, air-config.xml or airmobile-config.xml for AIR - scroll down until you see the <fonts> tag and you'll find a commented-out example. You can find a handy list of them in flash-unicode-table.xml.

"Only some of my characters are showing up!
This is a bit of a hairy bug, but it's probably this. Basically it can happen when you embed the same font in two different SWFs/SWCs that are used in one project. Say you have SWF A and SWF B that you include in your main project. SWF A embeds Arial and the characters a, b and c. SWF B embeds the full Arial font (same weight as the font in SWF A). If SWF A is compiled in your project first, then Flash will only take those glyphs (i.e. a, b, and c), ignoring those in SWF B. This is why only some characters in your TextFields are showing up. Take note that static TextFields also count towards embedded text. If you code in FlashDevelop you can click the [+] beside the SWF, and again on the font so see how many glyphs have been embedded.
As this bug doesn't look like it's going to get fixed, there's a few solutions you can employ:

I found all of these links useful when digging into this. The first two are manadatory reading, the rest explain the subject a bit better.

Code

I've created a project that includes everything I talked about here. It has the code and Flash files necessary to to just about all the types of font embedding you could wish for. You can download it here.

Files

Comments

Jackson Dunstan

What a great article and a handy reference. Thanks!

Khanou

Hi,

You can also use Fontswf to generate font in swf. It's included in the Flex SDK in the folder bin. Just run it through your cmd with -help as option. It's trivial use.

screenworker

Check the mimeType if no embed font is displayed.
One of them will work:

application/x-font
application/x-font-truetype
application/x-font-opentype
application/x-font-truetype-collection

Carl Schooff

I'm so glad even the smart people have trouble with this, and its not just me.
How adobe could have made something so convoluted is beyond me.
It's like you need a CS degree to make a dynamic textfield bold.
Thanks so much for deciphering it so well.

Sam Brick

Thanks for this! Really, really useful reference and will save the world millions of wasted hours in Flash/font pain...

Brian Rinaldi

Great reference post! In case you missed it, I referenced it in my weekly roundup of the best posts of the week which you can find here http://remotesynthesis.com/post.cfm/cool-stuff-with-the-flash-platform-2-18-11 (it is also distributed internally at Adobe).

I was wondering if you would take a moment and add a link to your post as a comment to the help docs in case others run into similar issues. I think, for instance, it might be helpful on this page http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-7f5f.html. We occasionally take links like yours and even make them part of the official documentation.

Thanks again and keep up the good work!

Brian Rinaldi
Web Community Manager
Adobe Systems

Damian Connolly

Official documentation eh? Cool! :D

Thanks Brian, the links already there

Fardeen

We all know how painfull it is to manage fonts properly with Flash so thank you for sharing :)

1misc1

Hey,
thx a lot. It was really the most completed introduction into embedding fonts I found in the web so far, and still: it did not work out for my project. As I use the embed tags,the "direct embedding way", as you described it, but in an external assets/fonts.as class, I was struggling to use the font in another class object/myText.as. And there is where the

private var myEmbeddedFont:Class;

you mentioned above, under the embed tag, gets important. I changed it into

public static var myEmbeddedFont:Class;

Then, in my object/myText.as, before I create the textformat, I have to call the class like this :

var myFont:Font = new Fonts.myEmbeddedFont();

In fact, it does not have to be referenced in a variable, because afterwards I create my textformat, how you mentioned it above :

var format:TextFormat = new TextFormat("[the fontname i specified in the embed tag]", 20);

I hope this help some people out there...
Greets,

Damian Connolly

Glad this post helped you a bit :)

To clarify, the private var myEmbeddedFont:Class part is needed for the Embed tag itself (it's part of how your data is embedded into the SWF), you can pretty much ignore it for fonts; it doesn't matter if it's private, public, or static.

As you mention, the important part is the fontName that you give your font.

Anonymous

Thanks for this post. One thing that I've been having difficulty with is how to go about embedding the less common weights of a font (eg, Condensed, Black, Light Italic, etc.) along with the more common ones and then referencing them both in the TextFormat setup. As you know, TextFormat can have properties of both bold and italic set to true or false, but there is no way to set "black" to true or false. Neither is there an obvious way to indicate a difference in the embed tag for these weights. Any light you might be able to shed on this would be very much appreciated.

Damian Connolly

For the 4 basic varieties (normal, bold, italic and bold-italic) it's quite easy. You make a separate import for each version, but taking care to specify the same fontName for each. So, for example, if I wanted to embed the normal and bold versions of a font, I'd do:

// embed the normal version
[Embed(source="../someFont.ttf", fontName = "myFont", fontWeight="normal", ...)]
private var myEmbeddedFontNormal:Class;
// embed the bold version
[Embed(source="../someFont.ttf", fontName = "myFont", fontWeight="bold", ...)]
private var myEmbeddedFontBold:Class;

Then create your TextFormat as normal. When in your TextField it comes across a <b> tag (set htmlText, not text), it'll use the bold font as needed.

For the others (Condensed, Black) etc., you'll need to embed them separately, as use them uniquely (i.e. a different fontName)

Anonymous

Can you please explain the line [Embed(source="../assets/test.swf", fontName="Courier New" )] in regard to using square brackets.

I'm a as3 flash design user and have never seen this sort of formatting before in code, so its a bit offputting.

I guess you'll have 3 kinds of people reading here, cs3/4/5 users, flashdesign users and then FLEX users. Most users of each are ignorant of the other kinds of users.

I'ld like to see a as3 code only embedded solution also, it may not be possible but you could call this out to improve your high quality tutorial.

Damian Connolly

The [Embed ...] tag is a metadata tag that we can us to embed images, xml, fonts, SWF files, etc and have them available when the SWF launches - no waiting for loading needed. What it does is embed the resource directly into your SWF file. If you're making games for distribution, you'd use this so you only send out one file, meaning it's much easier to distribute your game. You can read more about it here: http://www.adobe.com/devnet/flash/articles/embed_metadata.html.

All of the examples are for use directly in code. The pure as3 example would be the first option. It just directly embeds a font file into your SWF and doesn't touch CS at all - which, if you're like me, is good if you don't have it :)

The other examples (using a SWF and using a font symbol) need the Flash IDE to work. If you're a pure CS3/4/5 user, then you'll probably be most familiar with embedding characters through TextFields.

There is another method - embedding through CSS (you can read about it here: http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-7f5f.html), which I should probably include to round it off.

Matthew Cummings

Sweet Jezebel, you are my new favorite person. I googled forever to try and figure this out.

You came up with this "flash embedded font comes up in list but does not display" ... so you can see I was getting desperate with the googlings.

Russdogg

Thank you! The embedCFF parameter was what was tripping me up. Thanks again!

Anonymous

"t.embedFonts = true; // very important to set"

THANK YOU! NO ONE ELSES TUTORIAL HAD THIS AND I WAS GOING NUTS.

ericsoco

as the poster from adobe mentioned, the adobe docs are much better now on embedding fonts:
http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-7f5f.html

one format you didn't include in your post is using the @font-face rule in a stylesheet. this is my preferred method, mainly because it's closer to a format that html/js/css devs understand, and will probably be more accessible to people maintaining my code in the future (a need for my job building museum exhibits that will, with any luck, be on the museum floor for years).

thanks for the thorough post!

Damian Connolly

I looked at the @font-face embedding method, but I couldn't get it to work (I'm not sure it even does work) for AS3 applications, and I wanted the code provided to be as copy-pasteable as possible, no matter the type of project. I should probably include it all the same for completeness.

The Adobe docs have definitely improved since I wrote this! I'd still like them to devote a bit more time to clarifying the embedAsCFF property, as that's the one that seems to kill everybody that reads this post.

Thanks!

ericsoco

oh and -- the fontswf tool is another option. i haven't used this one, but it's an interesting option....
of course, you're not paid to write these posts, so i think we can forgive the omissions ;)

Anonymous

This is a real masterclasse for font embed!

THANK YOU!!!

I wasted 3 hour only for embedAsCFF trip!

Mighty Flash Gordon

Hi,

I have just come across this and it all seems a better way to embed fonts in flash. I hope this hasnt become dated.

I am using AS3 Flash CS5 (I am a AS3 newbie) and I am particularly interested in the way you use the swf to embed the font/s. I have a created a dynamic text field inside a MovieClip with CSS, here is a liitle bit of the code that makes the text field:

private function parseFile(xmlContent:XML):void
{
	// content
	var contentText:TextField = new TextField();
	contentText.styleSheet = styles;
	contentText.htmlText = xmlContent.mainPage.contents.text();
	contentText.width = contentText.textWidth;
	contentText.x = 0;
	contentText.y = 0;
	contentText.antiAliasType = "advanced";
	contentText.multiline = true;
	contentText.autoSize = "left";
	contentText.wordWrap = true;
	//contentText.embedFonts = true;
	contents.addChild(contentText);
}

I was wondering how your swf embed and also how to embed multiple fonts using this method and also how to implement it into my own project? Any help would be much appreciated.

Kind regards

Mighty Flash Gordon

Damian Connolly

I'll have to update the post to include using StyleSheets :)

Basically you choose your method of embedding above, and just specify the right fontFamily for your StyleSheet. A simple example using direct embedding:

package  
{
	import flash.display.Sprite;
	import flash.text.StyleSheet;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	
	// simple test document class
	public class TestEmbed extends Sprite
	{
		// embed our font
		[Embed(systemFont="Trebuchet Ms", 
			fontName = "myFont", 
			mimeType = "application/x-font",
			unicodeRange="englishRange",
			embedAsCFF="false")]
		private var myEmbeddedFont:Class;
		
		public function TestEmbed() 
		{
			// create our stylesheet
			// NOTE: the fontFamily is the fontName that you specify in the embed code above, NOT the actual name of the font
			var s:StyleSheet = new StyleSheet;
			s.setStyle( "p", { color:"#ff0000", fontFamily:"myFont", fontSize:20 } );
			
			// create and add our textfield
			var t:TextField	= new TextField;
			t.embedFonts	= true;
			t.autoSize		= TextFieldAutoSize.LEFT;
			t.styleSheet	= s;
			t.htmlText		= "<p>Hello World</p>";
			t.x	= t.y		= 20.0;
			t.rotation		= 5.0; // just to show that it's embedded
			this.addChild( t );
		}
		
	}

}

You can embed multiple fonts simply by using multiple Embed calls, if I understand your question correctly.

Mighty Flash Gordon

You have understood me correctly yes. keepin in mind that I am a total newbie with AS3. I was possibly looking at using your "Embedding using a SWF". My problem is that im using a xml file for data and css. e.g.

xml:
had to replace the "<>" with "[ ]"because I couldnt figure out how to post it with them in.
?xml version="1.0" encoding="UTF-8"?
[configSettings]

[mainPage]

[contents][![CDATA[[p align="left"/][c1/]This is a content text box
[c2/]more text than you can shake a stick at when living in the woods
[c3/]Another text field with css and xml which is selectable to
[c4/]and another one for good luck]]]
[/contents]

[/mainPage]
[/configSettings]

css:

c1 {
	font-family:Arial, Helvetica, sans-serif;
	font-size:20px;
	font-weight: bold;	
	color: #ff6699;	
}
c2 {
	font-family:Arial, Helvetica, sans-serif;
	font-size:15px;
	color: #33ccff;
}
c3 {
	font-family:Arial, Helvetica, sans-serif;
	font-size:24px;
	font-weight: bold;	
	color: #ff6600;	
}
c4 {
	font-family:Arial, Helvetica, sans-serif;
	font-size:12px;
	color: #ff3366;
}

and I'm also using greensocks XMLLoader e.t.c., which i have lots of code and wouldnt want to overload this post.

Damian Connolly

There's very little to change actually. Last night I mocked up a quick demo of a project in Flash. I have a style.css file in the same directory as the .fla with the contents:

p
{
	/** both "fontFamily" and "font-family" work */
	fontFamily:"Trebuchet Ms";
	color:#ff0000;
}

Then in my fla, I created a font symbol as described in the section "Embedding using a font symbol" (I know you want to do "Embedding using a SWF", but if you're coding in the same .fla file as your font, then this is the easiest way). The font has a linkage name of "myFont". Then in the first frame of the movie, I have this code:

// load our stylesheet
var urlLoader:URLLoader = new URLLoader;
urlLoader.addEventListener( Event.COMPLETE, this._onLoad );
urlLoader.load( new URLRequest( "style.css" ) );

// called when the css has loaded
function _onLoad( e:Event ):void
{
	// get our url loader and remove the event listener
	var urlLoader:URLLoader = e.target as URLLoader;
	urlLoader.removeEventListener( Event.COMPLETE, this._onLoad );
	
	// create our stylesheet and parse it
	var css:StyleSheet = new StyleSheet;
	css.parseCSS( urlLoader.data );
	
	// create our textfield
	var t:TextField 	= new TextField;
	t.styleSheet		= css; // set our stylesheet
	t.autoSize			= TextFieldAutoSize.LEFT;
	t.embedFonts		= true;
	t.htmlText			= "<p>Hello world</p>";
	t.x					= 20.0;
	t.y					= 20.0;
	t.rotation			= 5.0; // to show that it's embedded
	this.addChild( t );
}

If you run it, you'll see a TextField with the font embedded and the style coming from your css. If you want, send me your email address (go through the contact page), and I'll send you on the files.

Anonymous

I LOVE YOU THANK YOU!!!

Alex

MY HERO!
It was the freakin' embedAsCFF that was missing.

Anonymous

I was wondering if you could help with a problem I've been facing. I'm making a AIR app which has a input textfield which takes in a (language malayalam) karthika font. When I type in stuff in the text field it shows in the karthika font. But when I trace the value I get the output in English. I actually intend to write this value into a xml file. I have embedded the font via the flash ide with all glyphs but still same issue.

Thanks
Vaas

Graeme

> embedAsCFF="false"

Thank you, sir. A hundred times thank you. Saved a good few hours there.

Submit a comment

* indicates required