Wednesday 9 April 2008

Embedding dynamic fonts on Flash AS2

EDIT: READ THIS ONE INSTEAD, IT IS BETTER WRITTEN AND HAS BETTER INSTRUCTIONS.

IF YOU WANT TO GET LOST AND SEE WRONG EXAMPLES, GO AHEAD AND READ THIS ONE....



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 made me a son, like we say in Spain when somebody (or something sometimes) do something you really needed for you.

then I carried on researching for shared libraries... Hmm you 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 probably it is what Matt said in that forum but at that moment I had not idea how to use libraries...

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 embeded and it can be used now.

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

Step 3: We load main.swf (we have everythng we need loaded) and main.swf can use the librar of "preloader.swf".

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

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:

Character sauce:
Create an empty flash file on AS2.0.
Create a text box with the flash GUI.
Select any font and embed the characters you want.
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".

When you have the convert to movieclip box on screen, click on Export for runtime sharing.
Assign it a nice Identifier to it, something that will be used as a generic name for all the fonts you want to embed, something like : "dynamicFont".
Click on the URL box and write the name that is going to be this SWF file will have when exported.

I suggest something that will make it you identify your files easily: "embedFont1.swf"

Leave it published on a folder for several minutes.


Font container:

Create another empty flash file on AS2.0.

And on library click in new Symbol 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, and use the same Identifier too. Can be any name for this new object and make sure it is a movieClip.

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. It will get specially confusing when there are lots of other files in the same folder. So we will place a name like: "font1.swf"

We should have now two files on the folder:"
font1.swf" and "embedFont1.swf".


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 generateda 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 ("loaderA_mc",0);
this.createEmptyMovieClip ("loaderB_mc",1);
loaderA_mc._visible = loaderB_mc._visible = false;

_global._font = "nameOfYourFont";
_global._fontID = "1";

//we load the font container movieClip.
this.loaderA_mc.loadMovie (font1.swf);

// to make it more dynamic i have added a variable called "_global._fontID", that is the number of your font. (1 in the example);
//this.loaderA_mc.loadMovie ("font"+_global._fontID+".swf");

this.onEnterFrame = this.preoloader;

function preoloader () {
if (this.loaderA_mc.getBytesLoaded () > 0) {
if (loaderA_mc.getBytesLoaded () == loaderA_mc.getBytesTotal ()) {
//when the font SWF file is loaded, it will load the mainmovie, but you dont need to do it really.
this.loaderA_mc.loadMovie ("mainMovie.swf");
//we destroy this onEnterFrame and we create new functionality for another onEnterFrame if you want another preloader for the mainmovie.
//this.onEnterFrame = this.preloaderB;

//if you just want to show the real file just write this:

//_level0.loadMovie ("
mainMovie.swf");
delete
this.onEnterFrame
}
}
}


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

var my_fmt:TextFormat = new TextFormat();

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

this.createTextField("my_txt", this.getNextHighestDepth(), 40, 40, 260, 160);
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!.


Original idea in: Odd hammer
Preloader and more information: Quasimondo.com

Thanks to you both.


5 comments:

Unknown said...

I think the file you have to preload is actually font1Embed.swf (or both).

I'm trying something similar, but with a Japanese font, so my font1Embed.swf is a big file around 4MB.

The load for font1.swf is very fast and the preloader thinks it is done, but font1Embed.swf takes a long time to load in the background. As the imported file, it doesn't look like Flash includes font1Embed.swf in it's calculation for loading font1.swf.

Does that make sense? If so, is that right?

Unknown said...

@Patrick :
That is true, I didn't include a loader for the font#embed.swf .

I think I will have to revise it then.

But I have no time to do it myself for now. If you want to expand the article I will be happy to add your loader. It should be easy, right?

Unknown said...

Hi all,

I am working with chinese font...i embed the font same as u mentioned, its working fine, but when u give the command
my_txt.embedFonts = true;
my_txt._rotation = 15;

Its not showing any content....so please u have any sample file give me........

Thanks in advance
Rajasekaran

binay said...

hi, it works fine within the textfields in the main movie but it doesn't work in the loaded movie clip.

here's my code

var my_fmt:TextFormat = new TextFormat();
my_fmt.font = "Kozuka Gothic Pro R";
my_fmt.color = 0xFF0390;
my_fmt.underline = true;

txt.text = "fdsfsdこれはサンプルテキストです。 | 这是一个示例文本";
txt.embedFonts = true;
txt.antiAliasType = "advanced";


txt.setTextFormat(my_fmt);

binay said...

it's the code inside the loaded movie clip. I'll be glad if anyone can help me through