Wednesday, March 5, 2008

Dynamic TextFields Anti-Aliased for Animation and Readability using Dynamic HTML Text

This article will outline the following flash issues requiring understanding to utilize shared fonts in Flash:

  • How to build a shared library.
  • How to share fonts in a shared library.
  • How to plan for your fonts and their usage.
  • Implementing shared fonts in Dynamic TextFields with HTML text.

In my time with Flash the most common text-requirement in a Flash movie has been the following:

  1. The project requires text on the screen to be dynamic.
  2. The project requires that the text anti-alias well.
  3. The project requires that the dynamic text animate in some manner, at least into view, rather than simply suddenly being on the screen.
  4. The entire movie should be as small as possible to make it snappy over a thin and reasonable bandwidth.

While you hear less about requirement #4 over the years, mostly due to increases in bandwidth, depending on the size of the project and how many SWFs are getting created, you still likely have to think about file size. I would go so far as to say that even if it is not mentioned explicitly as a requirement, it is understood implicitly to be one.

On requirement #1, the simple answer is loading in the text data. While the technique dejur may have been LoadVars objects, now replaced by XML, the bigger issue is that you are working with a TextField in a Dynamic Text state. The font issues change depending on the state you are using.

On requirement #2, the answer would normally be to apply anti-aliasing for “readability” (advanced anti-aliasing) if you want the text as clear as is possible. Suddenly, in your Dynamic TextField you are now confronted with having to embed your font outline in this TextField. No problem.

On requirement #3, stuff starts getting more complicated. What you really need to do here is anti-alias for “animation” which conflicts with anti-alias for “readability” since the Flash User Interface only applies these options in a mutually exclusive manner. So you change it to “animation” since this eye-candy is a requirement not likely to go away.

Back to requirement #4, you render the FLA into a SWF and confirm that the file size remains quite reasonable despite the fact that you are embedding your font. You are thrilled with your result (even though you are anti-aliasing for “animation” and not “readability.”) Even if you have to duplicate the TextField, Flash is smart enough to not re-save the font outlines and double the size of your SWF when it renders. Great!

Enter dilemma:

While some project elements are able to completely co-exist in a single SWF, the far majority of the projects on which I have worked load a number of SWFs, usually all into a single Movie that works like a loading container. Sometimes, things get more complicated than even this (images loading into MovieClips, in SWFs, that are loading into other SWF containers, etc.) The dilemma arises on a number of levels when you begin to realize that you are embedding that same font into a number of movies. Here are the issues (there might be more, but these are my top two):

  1. Because you are placing font outlines in each movie (SWF) you are requiring additional bandwidth of the “web surfer” to re-download the font data for each movie (SWF) that loads.
  2. If at some point in the project, you suddenly have to change a font that was previously applied, you have to open each movie (SWF) and meticulously change each TextField, pointing it to the right font and re-embedding the new font.

The solution I am going to explain resolves both of these issue and in a fairly slick manner. I will also tack on a solution that allows you to anti-alias for both “readability” and “animation” at the end (but it comes with a warning.) Let’s get started.

How To Build A Shared Library

The answer to our font bandwidth issue is found in something called a shared library. This is far easier than it sounds, but can sometimes be difficult to find info on (hence the article here.) Here is how you build a shared library, step for step (note that there a a lot of steps, but I am outlining steps you probably do without thinking so not much of this will seem new):

(The following assumes you are using at least the Adobe Flash 8 Designer/Developer tool.)

  1. In Flash Designer, Create a new Movie (Flash Document.)
  2. Save the new file as “fontLibrary.fla” (call it whatever you want)
  3. Under File, Project properties, uncheck the “HTML” format and hit “OK” (we don’t need flash to create an HTML page for our fontLibrary.swf file.
  4. In the timeline, change the one available layer into a “Guide” (We don’t want to accidentally create anything on the stage. Our fontLibrary should have no “stage’ assets.)
  5. Now, in your project’s library, click the menu icon in the upper right corner of the library panel and select “New Folder.”
  6. Rename the new folder to “Shared Fonts.”
  7. Now, in your project’s library, click the menu icon in the upper right corner of the library panel and select “New Font.”
  8. Give your font a name that will make the most sense when you come back and visit this fontLibrary or any of your movies that will use your shared fonts later on. For example, as a standard, I name the font starting with an underscore character and the project name, like “_nxFrameworkFont” which helps later in a number of ways (I will show you that very soon.)
  9. Here is a big trick: Select your font name from the list (the one you want to embed) and be sure that none of the other boxes are checked (like Bold or Italics and size doesn’t matter here) and hit OK.
  10. Now, while I will explain this later, go ahead and create two more versions of your embedded font, one with the Bold box checked and one with the italics box checked. I named these “_nxFrameworkFont-bold” and “_nxFrameworkFont-italic” respectively.
  11. Drag all three of these fonts into the “shared fonts” folder you created before.
    Now we need to setup these new fonts for sharing.
  12. Select the first font you create, right-click it and select “Linkage”.
  13. Check the top three Linkage boxes: Export for ActionScript, Export for runtime sharing, and Export in first frame.
  14. You do not have to associate this with a class, but rather specify the name of this fontLibrary.swf in the URL field. In my project, the SWF will be rendered as “fontLibrary.swf” and so that is exactly what I write in the URL field.
  15. Apply step 14 above to all three fonts symbols you have created.
    Now, just save your work and render the SWF hitting [shift]+[F12].

You have completed the first step of building a sharedLibrary. Told you it was simple.

How to Share Fonts in a Shared Library

Now that you have your shared library, in my case named fontLibrary.swf, you need to use those fonts in your TextField animations in other movies (SWFs.) To demonstrate this, following these next steps:

  1. In Flash Designer, Create a new Movie (Flash Document.)
  2. Save the new file as “shell.fla” (call it whatever you want)
  3. We need to setup our shared fonts and this is simple. At the top of your Library panel for this project, notice that you have a pulldown menu that shows you other libraries you currently have open. Go ahead and select the fontLibrary.fla from the list.
  4. Now, drag the “shared fonts” folder to stage in your new “shell.fla” project.
  5. Notice that nothing appears on the stage, but if you switch back to your shell.fla library in the library panel you can see the fold and all of the fonts are imported.
  6. Notice that the font symbols state that they are “imported” – this is Flash doing the work of simply borrowing the outlines from the other SWF once this SWF and the fontLibrary SWF are both rendered.
  7. We need to create a movie clip to animate with dynamic text in it, so go ahead and draw a box of any color on the screen.
  8. Place a TextField above the box.
  9. Select both the box as well as the TextField and create a new MovieClip out of it by hitting the [F8] key.
  10. Be sure it is set to be a MovieClip and name it “mcMessage” and hit OK.
  11. Now in the properties, with the MovieClip on the stage selected, give it an instance name of “objMessage”
  12. Edit the MovieClip on the stage by double-licking it and select the TextField you created.
  13. We want to change this to a dynamic TextField that can work with HTML, so go head and switch its state to Dynamic Text, and confirm that it is set to Multiline and HTML Text in the properties. Below where you changed its state to Dynamic Text, give the field a name of txtDynamic (you do not need to give it a “Var” name.) Go ahead and uncheck “selectable” and “show border” if they are toggled in the “on” position.
  14. Now simply select the initial font we previously created and imported. Notice that because of the underscore “_” character, our font sits at or near the top of the list of available fonts.
  15. Return to the scene and save your work.

Now we want to dynamically add some text and do a little animation, so add a layer to your “shell.fla” project and hit [F9] on that layer to add some ActionScript. Add the following ActionScript to the frame:



import mx.transitions.*;
import mx.transitions.easing.*;

this.objMessage.txtDynamic.htmlText = "The quick brown fox jumped over the lazy dog!";
new Tween(this.objMessage, "_alpha", Strong.easeIn,0,100, 2, true);

This is what we are doing. The import statements allow us to easily programmatically Tween our MovieClip. Next, we are dynamically adding htmlText to our TextField. This could be coming from XML or a LoadVars object, but we are hard coding it for the example. Finally, we are tweening the alpha of the MovieClip from 0 to 100 over a period of 2 seconds, which basically fades in the image.

If you run the “shell” movie now ([ctrl]+[enter]) you will notice that the MovieClip fades in, including the text with your shared font, and all of the HTML formatting. Very cool. For fun now you should go back into the fontLibrary.fla and in each font symbol, change it to another font (remember, then must all match, the only difference being whether the bold or italic boxes are checked.) If you re-render the fontLibrary.swf, and (without re-rendering the shell.swf) run the shell.swf, it will now show your animation and text using the new font in the fontLibrary.swf!

You should, however be wondering how it is able to anti-alias for animation at this point without embedding the font or selecting that as an option in the TextField properties? As importantly, you might also be wondering how we are getting bold and italic text to show up since we only applied the font without the bold and italic options to our TextField. And what if we changed the htmlText so that the word lazy should show up both as bold AND italicized? Would that work? Could you have simply shared a single font with the bold and italic boxes checked and would that single shared font have solved everything? All of these questions are handled in the next section.

How to Plan for Your Fonts and Their Usage

The biggest issue in using shared fonts is getting them to act like embedded anti-alias for animation fonts do inside a TextField, but in some cases looking like anti-aliased for readability at the end. In nearly all cases, animation is a requirement, even if only for a second when the text shows up on the stage. So you will notice that while creating one uber shared font with bold and italic boxes checked will work with the HTML to look correct, suddenly the animation will go away (rather than fade in, the background box fades in over 2 seconds, but the text is immediately on the screen.) This is why we create multiple shared fonts, and this is how that works:

In flash we only applied our most simple shared font to our TextField (not the bold font or the italicized font symbol). When flash renders the HTML into the TextField, it can easily render that font under most circumstances. By default it renders this as if we have embedded the font and setup anti-aliasing for animation (again, this is the default behavior.)

Now, once it hits the first HTML bold tag or Italics tag, flash realizes that the font symbol we are applying doesn’t contain those font outlines. Flash then goes looking for those fonts and specifically searches in a particular order. That order seems to be (though I can’t say I figured this out by anything other than hit or miss) (1)first it looks in any font symbols available, (2) then it looks on the hard drive of the user, and finally (3) it uses the most generic version (_sans, _serif, _typewriter, etc) it can figure out to use. Here rests the magic. It finds the right font to apply in our other font symbols and applies them without breaking the anti-aliased for animation behavior. Magical! Again, if all of those outlines were in one font symbol, it would have broken our animation. Try it and you will see.

But what does this mean for any italicized bold text. When you are using shared fonts (or font symbols at any time) and flash encounters a font reference that it cannot resolve, your text just disappears. For example if the word “lazy” was supposed to appear as italicized bold text per the HTML in the TextField, then the txtDynamic TextField would render out “The quick brown foxed jumped over the dog” (and skipped rendering that word "lazy" altogether.) The solution is, as you are likely imagining, creating another shared font symbol with both the bold and italic boxes checked! And problem solved. Since most other special text effects are handled outside of font outlines (for example, underlining text is not an outline but a text effect) embedding those four font symbols solves our need to share fonts and achieve animation like embedded fonts.

Implementing Shared Fonts In Dynamic TextFields With HTML Text.

At this point you should be able to understand this very quirky (but consistent) solution and while it would be overkill to apply this to only one TextField in only one SWF, go back and consider the project that includes quite a number of SWFs all with their own TextFields and embedded fonts. If you implement this technique, and someone yells “font change!” at any point in your project, you can now handle it in one simple place and with one quick SWF render!

Anti-Aliasing For Readability Footnote

As promised, I will talk about implementing “Anti-Aliasing for Readability.” The issue here is that you want your font to animate BUT you also want it to look it’s absolute best for reading. Well, consider the following simple line of code:



this.objMessage.txtDynamic.antiAliasType = "advanced";


And now you still get animated text, but it is also anti-aliased for readability. But recall that this comes with a warning. Animating text that is anti-aliased for readability can be processor intensive (on the client-side at runtime.) I will describe how the work-around for this works (briefly… because there is a downloadable example!)

In a nutshell, whether you are programmatically animating using the Tween class, or if you are animating on the timeline, you would want to wait until the animation completed before changing the antiAliasType on the TextField to “Advanced” (which makes it resize a little because of the difference in rendering.) In the downloadable example I show you how to apply this both at the end of a timeline animation as well as when the motion completes in a programmatic Tween.

For future ideas, you might look into custom programmatic anti-aliasing which might help you find a middle ground between anti-alias for animation and anti-aliased for readability.

Now click here for the downloadable sharedFonts with HTML and annimation!

1 comment:

Anonymous said...

Hi
Give more ideas about adding the books and fonts in a library
E-datapro is equipped with the latest high speed scanning equipment image scanning and scanning services are probably one of the lowest cost services you will ever find.