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.

10 comments:

DB COAir said...

Any chance you can post your FLAs? I've been trying to make this work for weeks now and haven't been able to make it happen. I can see on your site and the other links that people have made it work so I'm guessing it's user error but I'm still not able to find the problem. Would really appreciate the samples.

Jaime Dominguez said...

Im triying to see why flash sometimes is showing my text boxes wrong sometimes. I think it is something to do with the preloader and the way it is done. It should work but there must be a bug somewhere in the code (or maybe player). Whenever I find out what is the problem I will post the final code. With tricks included!

If u still want the code send me you email address and I will email you it.

Damian said...

Hi Jaime

Would appreciate if you could share your FLAs, I'm problems getting it to work too!

My email address: huandamian(at)gmail(dot)com

My thanks in advance!

joyce+ said...

It is exactly what I want! thanks so much! But i've problem working on this too... Can I have the .fla files?

This is my email: joyce.liyanyee(at)gmail(dot)com

Great post:)

Jaime Dominguez said...

Hello Joyce,

I am waiting for Damian to send me his FLA files for me to be able to correct them.

I just am too busy to create an example from scratch. If you are in a rush, send me your FLAs, with only the code for the attempt to create dynamic fonts, and I will be able to correct them. :)

That goes for anyone else that is asking for the FLA.

kxalex said...

I did it and it works fine for me!
Thanks man!

Arvin W said...

Can u send fla ?

Paul B said...
This comment has been removed by a blog administrator.
Steven Burns said...
This comment has been removed by the author.
Steven Burns said...

You can avoid main.swf altogether if you create a library symbol (let’s call it “Main”) with all its contents and do the following in your top movie:
Frame 1: load the fonts
Frame 2: empty
Frame 3: if fonts not yet loaded go to frame 2
Frame 4: Instance of “Main” symbol.
This way you don’t need a “preloader” movie and a “main” movie, you just have one movie per project (and the font libraries which still are 2 SWF per font type, no workaround there, sorry).

It works for me, your mileage may vary.