Categories Displayed in Flash

Archive for the 'fonts' Category

Flash and Fonts: Sharing Embedded Fonts with multiple swfs ( Font.registerFont to the rescue)

Yet another day in the trenches debugging Embedded Fonts this time, using Embedded Font Assets in the Library, with multiple swfs that are a hierarchy like:

  • mainSwfWithFonts.swf
  • child.swf
  • grandchild.swf

A zip of 3 Fla's for this is here embeddedfontsharingacrossswfs

Conclusion.

  • make sure your Library Embedded Font is set to export on frame1, and is checkmarked to export for actionscript.
  • make sure that you  "Font.registerFont(YourFontClassNameGoeshere);" else while child.swf can access it's parent's swf fonts without any issues, grandchild.swf will NOT be able to use the embedded font tables.
  • avoid static text fields, or dynamic textfields with partial embedded character sets in multiple swfs,..only one can be used, else they will collide, first takes all.  Say you have a static textfield with "Hi" past this no other swfs fonts can be used, meaning your pretty much stuck with the characters H and i.
  • if your font appears in "()" Flash could not find the font on your filesystem and is using a mapped font instead.  Make sure the font is correctly installed, close down all the Fla's and edit the font mappings ( Edit> Font Mapping).

Testing

Behavior,

create a Font name it "Finky".  Create a textfield on stage and choose the font "Finky*"   (it should not appear (Finky*)  Rotate that TextField a few degrees... this will be invisible on Flash 9.  Go back to the Library and delete the Finky Font.   Turn publish size report on, Test Publish you'll get an output like and a blank stage.

Font Name                 Bytes        Characters
----------------------    ---------    --------------
Finky* Bold                      16
Myriad Pro Bold          24621     ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz

Note that the name in the Textfield* is just an alias to the 'real font' it it finds it it will replace it.

Create the Finky library again. and republish, note no characters are embedded and it still doesn't show up.

Font Name                 Bytes        Characters
----------------------    ---------    --------------
FinkRoman Bold                   18
Myriad Pro Bold               24621     ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz

Now in the TextField, Choose to embed the UPPERCase in the Embed... option, republish you will only see the capital letters, because in this case it's pulling from the Textfield and not the one in the library. Note how it's handing things off.

Font Name                 Bytes        Characters
----------------------    ---------    --------------
Finky* Bold                    4595     ABCDEFGHIJKLMNOPQRSTUVWXYZ
Myriad Pro Bold            25338     ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz

Note in this case the memory jumps up a ton, this is likely the size of the font character set.

Font Name                 Bytes        Characters
----------------------    ---------    --------------
FinkRoman Bold                35261     ABCDEFGHIJKLMNOPQRSTUVWXYZ

Now in the library right click and select Export For Actionscript, and Export in firstframe. Test Publish, note now we get every character under the sun. and the text shows up in the main swf and the child swf but not the grandchild swf!

Font Name                 Bytes        Characters
----------------------    ---------    --------------
FinkRoman Bold                66175     !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿˆ˜–—‘’‚“”„†‡•…‰‹›€™
Myriad Pro Bold               25756     ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz

Now try going back to the textfield and choose something other than letters (e.g. punctuation) as to embed..normally this would make only punctuation show up, but since we don't have any we shouldn't expect to see anything. But SURPRISE, they all show up!  This means that the TextField has the key to the font table and whatever it contains.

Lastly now use Font.registerFont(Finky) and test again, viola now all 3 swfs have access to the fonts.

This took several hours to figure out.  I thought originally it was Security.allowDomain, or loading into the same ApplicationDomain since there are the same Font objects.... but nope.

TIPS

1) You can use the neato Array.filter to help trace the fonts. e.g.

  1. var embeddedFonts:Array = Font.enumerateFonts(false);
  2.  
  3. embeddedFonts.sortOn("fontName", Array.CASEINSENSITIVE);
  4.  
  5. trace("Found Embedded Fonts " + embeddedFonts.filter(traceFontName));
  6.  
  7. function traceFontName(cur:*, ...rest):void{
  8.  
  9. trace(cur.fontName);
  10.  
  11. }
  12.  

2) You CANNOT use that iterator to expose fonts automatically in the Font.registerFont, Font instances from embedded have abstract Class that can't apparently be referenced.

Flash: Embedding Fonts via the Font Symbol

This is far tricker than I remember it being in Flash8. Again, since the introduction of AS3 it seems like bar for working in Flash for doing everyday things has gotten harder for people, instead of easier.

Embedding Fonts via a Font Symbol in the library, I believe used to allow textfields just to select that Font (denoted with an *) and that's all they had to do to embed a font. In AS3 it appears they have to add a few more steps. I was actually surprised at some of the results. The linkageID and Class name don't make a difference.

(Either JavaScript is not active or you are using an old version of Adobe Flash Player. Please install the newest Flash Player.)

Here's the Fla

I certainly wouldn't expect ExampleA and ExampleB to work they way they did.

I model this behavior as internal to the Flash player is a Embedded Font Table, that either has the character(s) or doesn't, and the embed property has access to those goodies or not. The character request is just an IDE trick/compiler hint, to build that font table if one hasn't already been provided, but doesn't exist anywhere in actionscript... a TextField doens't have embedCharacters, nor would that particularly make sense.

Metaphorically the behavior is a bit like having a locked-refrigerator full of food vrs going out to the OS to eat, and each swf as a guest has keys to to that or not. There is only room in the refridgerator for one gallon of milk in the door so even if that's partly empty (e.g. you only embedded capitals), if you try to put a full one in, it won't fit, until the previous one is unloaded. I have run into cases where one swf wouldn't share the fonts with another 'guest' swf, which I still haven't figured out yet.

Note you can test whether a font is embedded or not by rotating the TextField, else you may think it's embedded but since it's on your OS, it still shows up.

If you haven't you may want to check out loading Font Libraries dynamically. Here and Here

Flash + Fonts: autosize textfield html fix

More fun with text.  TextFieldAutoSize only appears to work when TextFields are set to MultiLine noWrap in the Text Tool properties editor, or in actionscript

  1.  
  2. txt.multiline = true;
  3.  
  4. txt.wordWrap = false;

Otherwise it's appeared to be ignored. I'm sure this is documented somewhere, it's not on the livedocs, but it would be nice if there was a warning for this if this actually the case.

Flash + Fonts: Dynamically Loaded Fonts + Embedding + CSS + HTML == Hell

I swear about every year I end up reexploring the dark internals to flash's murky font seas, lose a day to a weekend everytime.

Basically the embedded fonts + html is a fairly complicated beast, that in order to work has to be called in a very specific order to work.

Here's a new twist.  As I've covered in previous articles the ability to load fonts dynamically is very cool, but what of those textfields on stage used as placeholders? How do they join in the font fun?  THEY DON'T.   It doesn't appear possible to have them styled as CSS+HTML+Embedded, even if you set it to new text with CSS the text inside just dissapears.  However you can create a new TextField that does support those values at the exact same place, and swap them like:

  1.  
  2.                 //////////// Takes a clip on stage and replaces it with an 'identical' one ////////////////////////////////////////
  3.                 public static function  swapClip(txt : TextField) : TextField {
  4.                         trace("swapClip2..............." + txt.name);
  5.                         var par : DisplayObjectContainer = txt.parent;
  6.  
  7.                         var tf : TextField = new TextField();
  8.                         var ss : StyleSheet = new StyleSheet();
  9.                         var tff : TextFormat = txt.defaultTextFormat;
  10.                        
  11.                         var p : Object = new Object();
  12.                         p.fontSize = tff.size;
  13.                
  14.                         p.fontFamily = tff.font;
  15.                         //"Myriad Pro";
  16.                         p.color = tff.color;
  17.                         p.size = tff.size;
  18.                         ss.setStyle("p", p);
  19.                         //
  20.                         tff.font = tff.font;
  21.                         //"Myriad Pro";
  22.                         tf.defaultTextFormat = tff;
  23.                         // new TextFormat("Myriad Pro", 16, 0);  
  24.                         tf.styleSheet = ss;
  25.                        
  26.                        
  27.                         tf.width = txt.width;
  28.                         tf.height = txt.height;
  29.                         tf.x = txt.x;
  30.                         tf.y = txt.y;
  31.                         //      tf.border = true;
  32.  
  33.                         tf.embedFonts = true;
  34.                         tf.antiAliasType = AntiAliasType.ADVANCED;
  35.                         tf.selectable = true;
  36.                         tf.multiline = true;
  37.                         tf.wordWrap = true;
  38.                         tf.condenseWhite = false;
  39.    
  40.                         //      tf.rotation = 15;
  41.                         //      txt.visible = false;
  42.                         trace("swapClip htmlText " + txt.htmlText);
  43.                         var html : String = "<p>" + txt.text + "</p>";
  44.                         tf.htmlText = html;
  45.                         tf.name = txt.name + "";
  46.              
  47.                         //              par
  48.                         par.addChildAt(tf, par.getChildIndex(txt));
  49.                         par.removeChild(txt);
  50.                         return tf;
  51.                 }
  52.  

Weirdly you have to give it both TextFormat and styleSheet to get the similar formatting as the clip on stage, clearly Flash's internal renderer has significant internal state and both TextFormat or StyleSheet overlapp controlling different aspects of it.

Flash + Fonts:W TF?! just linking to a font, no embedding…13Kb increase in swf size!?

Trying to optimize a banner ad., baffling, a single textfield, no embedded fonts, just switching to a different font has HUGE differences in the swf size. Interestingly that actually embedding the glyphs don't seem to take up as much space as I would have though. Here's a size report with a bunchof textfields on stage:

Font Name Bytes Characters
---------------------- --------- --------------
DejaVu Sans Light 28510
Linux Libertine 26852
Warnock Pro SmBd 26184
Warnock Pro 25379
Chaparral Pro 20827
Myriad Pro 17713 abcdefghijklmnopqrstuvwxyz <--very little diff.
Myriad Pro 15541
Adobe Caslon Pro 11549
Kozuka Mincho Pro EL 3809
Franklin Gothic Medium 2697
_sans 2447
Arial 2447
_serif 2335
Tahoma 1819
Verdana 1445
Abadi MT 1183
Baskerville 1158
Abadi MT Light 1082
Trebuchet MS 335
Times 319
Microsoft Sans Serif 38
Arno Pro 30
Courier New 31
Letter Gothic Std 22
Courier New 19
Sveningsson 19
Wingdings 18
Arno Pro 18
AbcPrint 18
Georgia 17
Futura 17

The goal here is to have a lightweight placeholder font, so that the runtime fonts can be loaded up once. At the moment just mentioning Myriad Pro ends up taking as much space as the font library we created earlier (!). My present guess is that the size of the library is related to the number of characters inside it, some of the doubling may be the jump from small ascii tables, to big unicode tables.

As much as I love Myriad Pro, alternates with similar spacing and weight for MyriadPro (16K), are Georgia (18bytes), Arno Pro(30B), Trebuchet (335B), Abadi MT (1K)...more than doubling in size at every step!

UPDATE:

Something very wierd is going on.  In playing around with it, I was able to get one text field that had only 22Bytes and used Myriad Pro.  However other fields that looked identical in the properties panel, when turned on ended up being 17Kb.  I'm wondering if somehow turning on/off embedding causes this switch.

Flash: Multiple Runtime Font Sharing Embedding with only Partial Character sets: How To.

Here's another example of runtime font loading, this time using html text, multiple flavors of the font library, in two separate swf libs, one with the regular font, the other with the bold, italic, bold italic flavors. Typically these would be loaded at different times, but this example should give you the basic idea.

The multiple font lib built by FlashDevelop + Flex 3.0 as "FontLibs.swf", being output as 'MyriadProExtendedFontLibs.swf', the one we created in the previous is now being loaded as 'MyriadProRegMinLib.swf'

package{ import flash.display.Sprite;import flash.text.Font;

public class MyriadExtendedLib extends Sprite

{

[Embed(source='C:/WINDOWS/Fonts/MyriadPro-Bold.otf', fontWeight='bold', fontName='Myriad Pro', unicodeRange='U+0020-U+0020,U+0021-U+0021,U+0022-U+0022,U+0023-U+0023,U+0024-U+0024,U+0025-U+0025,U+0026-U+0026,U+0027-U+0027,U+0028-U+0028,U+0029-U+0029,U+002A-U+002A,U+002B-U+002B,U+002C-U+002C,U+002D-U+002D,U+002E-U+002E,U+002F-U+002F,U+0030-U+0030,U+0031-U+0031,U+0032-U+0032,U+0033-U+0033,U+0034-U+0034,U+0035-U+0035,U+0036-U+0036,U+0037-U+0037,U+0038-U+0038,U+0039-U+0039,U+003A-U+003A,U+003B-U+003B,U+003C-U+003C,U+003D-U+003D,U+003E-U+003E,U+003F-U+003F,U+0040-U+0040,U+0041-U+0041,U+0042-U+0042,U+0043-U+0043,U+0044-U+0044,U+0045-U+0045,U+0046-U+0046,U+0047-U+0047,U+0048-U+0048,U+0049-U+0049,U+004A-U+004A,U+004B-U+004B,U+004C-U+004C,U+004D-U+004D,U+004E-U+004E,U+004F-U+004F,U+0050-U+0050,U+0051-U+0051,U+0052-U+0052,U+0053-U+0053,U+0054-U+0054,U+0055-U+0055,U+0056-U+0056,U+0057-U+0057,U+0058-U+0058,U+0059-U+0059,U+005A-U+005A,U+005B-U+005B,U+005C-U+005C,U+005D-U+005D,U+005E-U+005E,U+005F-U+005F,U+0060-U+0060,U+0061-U+0061,U+0062-U+0062,U+0063-U+0063,U+0064-U+0064,U+0065-U+0065,U+0066-U+0066,U+0067-U+0067,U+0068-U+0068,U+0069-U+0069,U+006A-U+006A,U+006B-U+006B,U+006C-U+006C,U+006D-U+006D,U+006E-U+006E,U+006F-U+006F,U+0070-U+0070,U+0071-U+0071,U+0072-U+0072,U+0073-U+0073,U+0074-U+0074,U+0075-U+0075,U+0076-U+0076,U+0077-U+0077,U+0078-U+0078,U+0079-U+0079,U+007A-U+007A,U+007B-U+007B,U+007C-U+007C,U+007D-U+007D,U+007E-U+007E,U+00A9-U+00A9,U+00AE-U+00AE,U+00B7-U+00B7,U+02C6-U+02C6,U+02DC-U+02DC,U+2013-U+2013,U+2014-U+2014,U+2018-U+2018,U+2019-U+2019,U+201A-U+201A,U+201C-U+201C,U+201D-U+201D,U+201E-U+201E,U+2020-U+2020,U+2021-U+2021,U+2022-U+2022,U+2026-U+2026,U+2030-U+2030,U+2039-U+2039,U+203A-U+203A,U+20AC-U+20AC,U+2122-U+2122')]

public static var _MyriadProBold:Class;

[Embed(source='C:/WINDOWS/Fonts/MyriadPro-BoldIt.otf', fontWeight='bold', fontStyle='italic', fontName='Myriad Pro', unicodeRange='U+0020-U+0020,U+0021-U+0021,U+0022-U+0022,U+0023-U+0023,U+0024-U+0024,U+0025-U+0025,U+0026-U+0026,U+0027-U+0027,U+0028-U+0028,U+0029-U+0029,U+002A-U+002A,U+002B-U+002B,U+002C-U+002C,U+002D-U+002D,U+002E-U+002E,U+002F-U+002F,U+0030-U+0030,U+0031-U+0031,U+0032-U+0032,U+0033-U+0033,U+0034-U+0034,U+0035-U+0035,U+0036-U+0036,U+0037-U+0037,U+0038-U+0038,U+0039-U+0039,U+003A-U+003A,U+003B-U+003B,U+003C-U+003C,U+003D-U+003D,U+003E-U+003E,U+003F-U+003F,U+0040-U+0040,U+0041-U+0041,U+0042-U+0042,U+0043-U+0043,U+0044-U+0044,U+0045-U+0045,U+0046-U+0046,U+0047-U+0047,U+0048-U+0048,U+0049-U+0049,U+004A-U+004A,U+004B-U+004B,U+004C-U+004C,U+004D-U+004D,U+004E-U+004E,U+004F-U+004F,U+0050-U+0050,U+0051-U+0051,U+0052-U+0052,U+0053-U+0053,U+0054-U+0054,U+0055-U+0055,U+0056-U+0056,U+0057-U+0057,U+0058-U+0058,U+0059-U+0059,U+005A-U+005A,U+005B-U+005B,U+005C-U+005C,U+005D-U+005D,U+005E-U+005E,U+005F-U+005F,U+0060-U+0060,U+0061-U+0061,U+0062-U+0062,U+0063-U+0063,U+0064-U+0064,U+0065-U+0065,U+0066-U+0066,U+0067-U+0067,U+0068-U+0068,U+0069-U+0069,U+006A-U+006A,U+006B-U+006B,U+006C-U+006C,U+006D-U+006D,U+006E-U+006E,U+006F-U+006F,U+0070-U+0070,U+0071-U+0071,U+0072-U+0072,U+0073-U+0073,U+0074-U+0074,U+0075-U+0075,U+0076-U+0076,U+0077-U+0077,U+0078-U+0078,U+0079-U+0079,U+007A-U+007A,U+007B-U+007B,U+007C-U+007C,U+007D-U+007D,U+007E-U+007E,U+00A9-U+00A9,U+00AE-U+00AE,U+00B7-U+00B7,U+02C6-U+02C6,U+02DC-U+02DC,U+2013-U+2013,U+2014-U+2014,U+2018-U+2018,U+2019-U+2019,U+201A-U+201A,U+201C-U+201C,U+201D-U+201D,U+201E-U+201E,U+2020-U+2020,U+2021-U+2021,U+2022-U+2022,U+2026-U+2026,U+2030-U+2030,U+2039-U+2039,U+203A-U+203A,U+20AC-U+20AC,U+2122-U+2122')]

public static var _MyriadProItalBold:Class;

[Embed(source='C:/WINDOWS/Fonts/MyriadPro-It.otf', fontName='Myriad Pro', fontStyle='italic', unicodeRange='U+0020-U+0020,U+0021-U+0021,U+0022-U+0022,U+0023-U+0023,U+0024-U+0024,U+0025-U+0025,U+0026-U+0026,U+0027-U+0027,U+0028-U+0028,U+0029-U+0029,U+002A-U+002A,U+002B-U+002B,U+002C-U+002C,U+002D-U+002D,U+002E-U+002E,U+002F-U+002F,U+0030-U+0030,U+0031-U+0031,U+0032-U+0032,U+0033-U+0033,U+0034-U+0034,U+0035-U+0035,U+0036-U+0036,U+0037-U+0037,U+0038-U+0038,U+0039-U+0039,U+003A-U+003A,U+003B-U+003B,U+003C-U+003C,U+003D-U+003D,U+003E-U+003E,U+003F-U+003F,U+0040-U+0040,U+0041-U+0041,U+0042-U+0042,U+0043-U+0043,U+0044-U+0044,U+0045-U+0045,U+0046-U+0046,U+0047-U+0047,U+0048-U+0048,U+0049-U+0049,U+004A-U+004A,U+004B-U+004B,U+004C-U+004C,U+004D-U+004D,U+004E-U+004E,U+004F-U+004F,U+0050-U+0050,U+0051-U+0051,U+0052-U+0052,U+0053-U+0053,U+0054-U+0054,U+0055-U+0055,U+0056-U+0056,U+0057-U+0057,U+0058-U+0058,U+0059-U+0059,U+005A-U+005A,U+005B-U+005B,U+005C-U+005C,U+005D-U+005D,U+005E-U+005E,U+005F-U+005F,U+0060-U+0060,U+0061-U+0061,U+0062-U+0062,U+0063-U+0063,U+0064-U+0064,U+0065-U+0065,U+0066-U+0066,U+0067-U+0067,U+0068-U+0068,U+0069-U+0069,U+006A-U+006A,U+006B-U+006B,U+006C-U+006C,U+006D-U+006D,U+006E-U+006E,U+006F-U+006F,U+0070-U+0070,U+0071-U+0071,U+0072-U+0072,U+0073-U+0073,U+0074-U+0074,U+0075-U+0075,U+0076-U+0076,U+0077-U+0077,U+0078-U+0078,U+0079-U+0079,U+007A-U+007A,U+007B-U+007B,U+007C-U+007C,U+007D-U+007D,U+007E-U+007E,U+00A9-U+00A9,U+00AE-U+00AE,U+00B7-U+00B7,U+02C6-U+02C6,U+02DC-U+02DC,U+2013-U+2013,U+2014-U+2014,U+2018-U+2018,U+2019-U+2019,U+201A-U+201A,U+201C-U+201C,U+201D-U+201D,U+201E-U+201E,U+2020-U+2020,U+2021-U+2021,U+2022-U+2022,U+2026-U+2026,U+2030-U+2030,U+2039-U+2039,U+203A-U+203A,U+20AC-U+20AC,U+2122-U+2122')]

public static var _MyriadProItal:Class;

public function MyriadExtendedLib()

{

super();

Font.registerFont(_MyriadProBold);

Font.registerFont(_MyriadProItalBold);

Font.registerFont(_MyriadProItal);

}

}

}

And the consumer of the fonts

  1. package {import flash.display.Loader;import flash.display.Sprite;
  2.  
  3. import flash.events.Event;
  4.  
  5. import flash.net.URLRequest;
  6.  
  7. import flash.text.*;
  8.  
  9. public class MultiFontLoader extends Sprite {
  10.  
  11. public function MultiFontLoader() {
  12.  
  13. loadFont("MyriadProRegMinLib.swf");
  14.  
  15.                loadFont("BaskervilleRegFontLib.swf");
  16.  
  17.                loadFont("MyriadProExtendedFontLibs.swf", true);
  18.  
  19. }
  20.  
  21. private function loadFont(url:String, complete:Boolean = false):void {
  22.  
  23. var loader:Loader = new Loader();
  24.  
  25. if (complete) {
  26.  
  27. loader.contentLoaderInfo.addEventListener(Event.COMPLETE, fontLoaded);
  28.  
  29. }
  30.  
  31. loader.load(new URLRequest(url));
  32.  
  33. }
  34.  
  35. private function fontLoaded(event:Event):void {
  36.  
  37. drawText();
  38.  
  39. }
  40.  
  41. public function drawText():void {
  42.  
  43. var tf:TextField = new TextField();
  44.  
  45. tf.defaultTextFormat = new TextFormat("Myriad Pro", 16, 0);
  46.  
  47. tf.embedFonts = true;
  48.  
  49. tf.antiAliasType = AntiAliasType.ADVANCED;
  50.  
  51. tf.multiline = true;
  52.  
  53. tf.autoSize = TextFieldAutoSize.LEFT;
  54.  
  55. tf.border = true;
  56.  
  57. tf.htmlText = "<p><b>Troy</b> was <b><i>here</i></b><br/> <font face='Baskerville'>Scott was</font> <i>here too</i><br/>...:;*&amp;^% </p>";
  58.  
  59. tf.rotation = 15;
  60.  
  61. addChild(tf);
  62.  
  63. }
  64.  
  65. }
  66.  
  67. }