Fading and masking with device fonts
December 29th, 2006 . by polyGeekExcerpt from the Flash LiveDocs, emphasis added:
Which, you will find out shortly isn’t entirely true.
Here’s how embedding vs device fonts works: when you embed a font the characters that you choose to embed are added to the SWF at publish time as shapes. In essence they are no different than complex shapes you might create with the pen tool. Device fonts by contrast are completely different because the font shapes are not included with the SWF. (Note: dynamic TextFields must use either embedded fonts or device fonts. There is no third option so essentially, if you don’t embed you are using device fonts.)
When a user runs your SWF on their machine and the Flash player gets to a TextField that uses a device font then the player asks the host computer, “What is your default sans-serif font.” - or whatever it was you specified. This is pretty much the same thing that happens with an HTML webpage. Since the Flash player doesn’t have the font shapes it can’t do things like change the _alpha or use the text as a mask.
“So why not just embed the font all the time?” you might ask.
The main reason I’ve had to use device fonts here at XBox.com and Zune.net is that we have to make our Flash apps accessible to an international audience. The text is populated from an XML file so that our sister sites in other countries can add their own text, in their language, to the XML file and it will populate the TextFields accordingly. If we had used an embedded font then they wouldn’t be able to change the text to Japanese, or Russian or whatever. Of course if you use Japanese text in the XML file then the user will have to have a default Japanese font on their computer.
So how do you get around this?
Flash 8 introduced Filters and the cacheAsBitmap property. With that you can tell Flash to treat the text as a bitmap. In essence that gives the Flash player the shapes it needs to alter the _alpha or use the text as a mask. The downside to this is that the text becomes aliased - looks jagged. Since you have to use a filter to get this to work then go ahead and use the blurFilter and apply a very slight blur to the font. That’s a poor man’s way of treating the text as anti-aliased. It won’t look nearly as good as it would if it had been rendered with the Saffron text renderer built into Flash 8 but it’s good enough.
I got the idea to try this while driving home one day. (Sometimes being stuck in traffic has it’s advantages.) I expected it would work but I also expected that the TextField would now be rendered as a bitmap and wouldn’t be editable. I was trying to think up tricks that I could use to be able to change the text property but fortunately I didn’t have to. It still just works. (I wonder if Tinic Uro had any idea this would work when he baked in the Filter classes to Flash 8?)
Here’s an example of a SWF using a device font as a mask while the _alpha of the text is oscillating between 25-100%. You can click on the different languages to see how device fonts are essential for internationalization. The text is stored in an array. If you don’t have a particular font then you’re going to see some ugliness.
Here is the essential code to make this work. The instance name for the TextField is txt and the maskee is wave. Download the example.
// create a blur filter for the TextField
import flash.filters.BlurFilter;
var filter:BlurFilter = new BlurFilter(1.2, 1.2, 3);
var filterArray:Array = new Array();
filterArray.push(filter);
txt.filters = filterArray;
// cache both the mask and maskee as bitmaps
txt.cacheAsBitmap = true;
wave.cacheAsBitmap = true;
wave.setMask(txt);
Now for the bad news, you still can’t rotate the text. The good news is that this works for input TextFields as well. You can still type along in the TextField and the text will mask and fade. Give it a try in the example above.
I would caution developers to not use this unless the really need to. The Saffron text renderer is really top notch and makes Flash text look great.
Note: I’ve done some Googling and can find only one other person has run across this trick. Good work Scott as far as I can tell you deserve credit for finding it first.
By the way, this is by my count the third seemingly impossible thing I’ve done with Flash. I think I’ll treat myself to breakfast at Milliways now. :-)












You could use BitmapData.draw() to create a graphical copy of the textfield and then rotate it. (of course it will be harder to scroll it ;) )
import flash.display.BitmapData;
//var tf:TextField;
//var copy:MovieClip;
var bmp:BitmapData = new BitmapData(tf._width, tf._height, false);
bmp.draw(tf);
copy = this.createEmptyMovieClip(”copy”, this.getNextHighestDepth());
copy.attachBitmap(bmp, copy.getNextHighestDepth());
copy._rotation = 90;
@Vladimir, excellent point. I had expected that I would have to do something like that for the fading and masking but it sort of worked by accident by just using Filters. One of the few times something turned out to be a lot easier than expected. :-)
The downside to using the BitmapData class is that the rotated text isn’t dynamic but in most cases it wouldn’t need to be. If one really needed to update the text then it wouldn’t take much work to update the TextField and then recopy it.
I’m lovin’ that BitmapData class more and more all the time. :-)
Here’s your code again with a few extra pieces.
import flash.display.BitmapData; var tf:TextField = this.createTextField("txt", 0, 0, 0, 0, 0); tf.autoSize = true; tf.background = true; tf.backgroundColor = 0x333333; tf.text = "Happy New Year"; var copy:MovieClip = this.createEmptyMovieClip("copy", 1); var bmp:BitmapData = new BitmapData(tf._width, tf._height, false); bmp.draw(tf); copy = this.createEmptyMovieClip("copy", this.getNextHighestDepth()); copy.attachBitmap(bmp, copy.getNextHighestDepth()); copy._rotation = 90;Ouch, I was just messing around and discovered that you don’t want to use the above approach at anything other than 90 degrees _rotation. Everything else looks like cack!
Is it possible to do the same with Flash MX? for flash plaeyr 7? something with BitmapInstance?
You know, I’ve never used BitmapInstance before. I took a quick look at it and didn’t see anything that would work but I’m not 100% certain.
I’m trying to use this technique; however, I’ve found that if you add letterSpacing (tfm.letterSpacing = 2), the whole thing breaks. Any ideas?
BTW, the letterSpacing only breaks this on macs.
@Albert, nice catch that the letterSpacing is an issue on Macs. As much as we like to think that Flash is consistent across platforms it just isn’t quite true.
I don’t really have any suggestions to offer, other than don’t use letterSpacing. I don’t have a Mac to test on so I wouldn’t know if i found a solution or not.
If you can could you describe what happens on the Mac with letterSpacing? I’m not really sure what “breaks apart” might look like.
Device Fonts und Alpha Tween…
2 Links die sich mit diesem Problem beschäftigen:http://blog.scottgmorgan.com/php/default.php?topicID=170&contentID=739&rowID=103http://polygeek.com/253_adobeflash/actionscript_fading-and-masking-with-device-fonts
…
this really bugs me. It’s like that crap about not being able to fade/mask device fonts. I don’t like limitations. So I figured out a way to do it. Open the page below to test it out for …
Astro may add fading and masking of device fonts without the cashAsBitmap hack. …
http://polygeek.com/253_adobeflash/actionscript_fading-and-masking-with-device-fonts …
nice trick :) also published in http://flashunlimited.blogspot.com/
Leave a Reply