Friday 4 September 2009

Embedding dynamic fonts on Flash AS2.(Better explanation)

Today after a couple of years on and off (more off than on) researching about embeding fonts on flash. I found a real solution today. The solution was explained on a comment in another blog like nothing important, but I can tell you it was really good for me to see this after tlooking for a solution this long.

It was a bit confusing for me so I carried on researching for shared libraries... Hmm I can't change the library dynamically. But can load flash files that has static libraries... I got me thinking.... I started realizing what was it...

I came with a solution which probably is what Matt said in that forum but at that moment I had not idea how to use libraries... so for the unexperienced I will explain it properly.


Anyway, this is how it works:
Step 1: The preloader loads the font1.swf that has as library the font1Embed.swf. That means it has the font embedded and it can be used now.

Step 2: All the library components can be used on preloader.swf

Step 3: We load main.swf which can use "preloader.swf" 's library.

It is easy once you understand it.... The great thing is you can load any library dynamically.

I will explain how to get dynamic fonts right now, step by step:

Ingredients:

  • a SWF file for the preloader,
  • 2 SWFs per font
  • any SWF that uses the font.

Cooking Time:
  • 10 to 15 mintues.
  • and then 3 minutes per font.

Preparation:

We are gonna use Arial font for this example, so wherever I say Arial , use any font you want


Character sauce:

Create an empty flash file on AS2.0.
Create a text box with the flash GUI.
Select Arial font and embed the characters you want. I normally add a text that contains at least one character bold, italic, bold+italic and normal.
Convert that text box into a movie Clip, or better said: put the text inside a movieclip.

Normally when I cook texts I assign names to the instances on the stage as "label_txt" for the text and "text_mc" for the movieclip. You can tell what kind of object is everything with just checking "_mc" or "_txt". In this example it doesnt matter as we are not going to use instances, only library objects.

When you have the convert to movieclip dialog window on screen, click on Export for runtime sharing.

Click on the URL box and write the name that is going to be this SWF file will have when exported.

We are preparing the Arial font so to make things clear name it "Arial_chars.swf".

Leave it published with that same name on the same folder as the preloader for several minutes.


Font container:

Create another empty flash file on AS2.0.

And on library click in new Symbol> Movieclip and then click on "Import for runtime sharing" it will ask you for an URL and identifier. Place the same name of the SWF file you just exported in Step1.

Then drag this new symbol into the Stage, anywhere.

Export the Flash file to the same folder of before. Use a name that will help you matching this file and the other exported file: "Arial.swf".

We should have now two files on the folder:"Arial
.swf" and "Arial_chars.swf".


(optional)
Placing all fonts in a special folder:

Placing the font files in a "fonts" folder requires you to edit all URLs from the properties dialog window relative to the preloader. That means that if you place all fonts in a folder called "fonts", and that folder is a inside the folder that contains the preloader, URLS on the properties/linkage dialog box must be: "fonts/Arial_Chars.swf" in the both characters files
.


Preloader:

We need to load all of these fonts before the real flash movie begins. So we are going to create a preloader, load the fonts first and load the main movie afterwards.

I generated a FLA with some code for it. It is a simple loader. I place the code as I have told you I will explain everything!


on Frame 1:
this.createEmptyMovieClip ("dummy",0);
this.dummy._visible = false;

_global._font = "Arial"; // or any font that you want to embed...

this.dummy.loadMovie (_global._font+".swf");//first preload the shared library
this.onEnterFrame = this.preload1;

function preload1 () {

if (this.dummy.getBytesLoaded () > 10) {
if (dummy.getBytesLoaded () == dummy.getBytesTotal ()) {
this.dummy.loadMovie ("main.swf");//also preload the main movie
this.onEnterFrame = null;
} else {
// add some progress display here
}
}
}


Then on the main flash file you need to create all of this code in order to test it:

my_fmt.font = _global._font ;
my_fmt.size = 40;

this.createTextField("my_txt", this.getNextHighestDepth(), 40, 40, 400, 30160);
my_txt.wordWrap = true;
my_txt.embedFonts = true;
my_txt.text = "Hello Mundo!";
my_txt.setTextFormat(my_fmt);
my_txt._rotation = 15;


Now you have to publish this test file as "mainMovie.swf" and the preloader as anyname.. "preloader.swf"?... all files need to be on the same folder.

Now if you publish all files with the correct names and folder , whenever you start the preloader it whould work.

Add glass sugar, and a smile, there you have what you have been looking for for ages!.


IMPORTANT NOTE: I have discovered that if you have at least one character embedded on your main flash movie this method wont work as it wont be using the external character set but the internal one. and this happens in ActionScript 2 and 3.


Thanks to Matt for the clever post in
Odd hammer.
Preloader and more information: Mario at Quasimondo.com

Thanks to you both.