0
votes

I have a project using flash (and AIR for android and eventuall iOS) for translating some phrases. Although most fonts are fine there are some that I have to load after the user has chosen the languages. Over a year ago I generated a couple of swf files (Bengali and Urdu) and put them on my web server. The flash application then loads them when required and everything is OK... However as I am nearing implementing the project I thought I should generate the swf files for the other languages that are in the pipeline and for some reason I can't manage it! Needless to say I have misplaced (tidied) the original AS3 source for the two fonts I have done.

package   
{  
    import flash.display.Sprite;  
    import flash.events.Event;  
    public class ArabicF extends Sprite   
    {       
        [Embed(source = "trado.ttf",
        fontName = "ArabicX",
        fontFamily = "ArabicY",
        fontWeight = "normal",
        fontStyle = "normal",
        mimeType = "application/x-font",
        advancedAntiAliasing="true",
        embedAsCFF="true")]  
        public static const ArabicZ:Class;  
    }   
}  

This has expanded from a much simpler form as I added things to get it to work and I must have tried all permutations of true and false. I load the swf ok but then can't extract the class. With the two fonts I embedded before the swf class and the parameter all have the same name and they work fine (i.e. Urdu.swf then later: var FontClass:Class = evt.target.applicationDomain.getDefinition("Urdu") as Class; and then Font.registerFont(FontClass.Urdu);
in the calling .as application with the above Arabic.swf I try

trace("1 Arabic "+evt.target.applicationDomain.hasDefinition("ArabicF"));  
trace("2 Arabic "+evt.target.applicationDomain.hasDefinition("Arabic"));  
trace("3 ArabicX "+evt.target.applicationDomain.hasDefinition("ArabicX"));  
trace("4 ArabicY "+evt.target.applicationDomain.hasDefinition("ArabicY"));  
trace("5 ArabicZ "+evt.target.applicationDomain.hasDefinition("ArabicZ"));  

but all return false

PS also tried generating the Arabic.swf using fontswf.bat which again seems to make a very similar swf file which is loaded but I can't extract the class from it

PPS I'm using flashdevelop and the font swf are set up as AS3 standard project compiler options.

2
There are several ways to debug this kind of problem. First, you could check that the class is actually exported inside the SWF file (using the link-report.xml or a tool like SWF Investigator (labs.adobe.com/technologies/swfinvestigator). Then, you can see, once your font library SWF is loaded, what Font.enumerateFont() gives you. The thing is, I am not sure that the way you embedded your fonts creates class definitions matching exactly the name you gave.Antoine Lassauzay
Antoine. Thanks very much for the pointer to swfinvestigator it seems A1 and will no doubt help me sort this out. At the moment I can find hardly any difference between the swf I made now and the ones from a year ago. After I changed the target to flash 9 from flash 10 they were very close. The old one contains extra tag DefineFontName and has DefineFont3 where the new one has DefineFont4. It certainly looks to contain classes ArabicF and ArabicF_ArabicZ so I would have thought the getDefinition() would work even if there was something wrong with the font!paddyg

2 Answers

2
votes

I don't use Flash Develop, but perhaps I can offer some perspective from my implementation.


If I wanted to embed Arial, the embedding swf would "Export for ActionScript" the embedded font. In its document class, use registerFont() as below:

Font.registerFont(Arial);

Like every other swf, you'd use a Loader to import it into your runtime, and at that point, the font will be available to your global table. You can query the complete list of registered fonts using enumerateFonts().

var fontList:Array = Font.enumerateFonts();
for (var i:int = 0; i < fontList.length; i++) {
    trace(fontList[i].fontName);
}

Assuming we've got a TextField called "txt", you can then implement that font with setTextFormat() like so:

var format:TextFormat = new TextFormat();
format.font = "Arial";
txt.embedFonts = true;
txt.antiAliasType = AntiAliasType.ADVANCED;
txt.setTextFormat(format);
txt.defaultTextFormat = format;

A disclaimer from Adobe on the use of these last two settings:

"When you apply a TextFormat object to a text field using the TextField.defaultTextFormat property or the TextField.setTextFormat() method, only its defined properties are applied. Use the TextField.defaultTextFormat property to apply formatting BEFORE you add text to the TextField, and the setTextFormat() method to add formatting AFTER you add text to the TextField."

As I said before, my workflow doesn't utilize Flash Develop, but rather Flash IDE to embed the fonts into the swfs. Your results may vary, but be aware you must set embedFonts to true, or it won't respond to your embedded font. I've lost hair on that issue before.

Hope that helps. Cheers,

1
votes

OK In case someone else runs into similar problems this is stage one of the answer (really the answer to my original question) still have to sort out how to get the font to be used in the flash.font.engine apparatus!

The critical parts are:

Point #1. the embedded font swf must have a name that doesn't clash with ANY name registered in the calling script. Bizzare and (as far as I could search) undocumented. i.e. I have a list of languages uploaded via xml services to an xml object and that includes for instance 'English' however the font loading doesn't work until I make the loadable font file into 'EnglishF.swf' The obvious choice of just 'English.swf' fails. So my embedded font source is now called EnglishF.swf and reads:

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

Security.allowDomain("*");
/**
 * ...
 * @author patrick
 */
public class EnglishF extends Sprite 
{       
    [Embed(source = "Kingthings Exeter.ttf",
        fontName = "EnglishF",
        fontFamily = "EnglishF",
        fontWeight = "normal",
        fontStyle = "normal",
        mimeType = "application/x-font",
        advancedAntiAliasing="true",
        embedAsCFF="true")]
        public static var myFont:Class;
}   
}  

and the using script goes:

private function fontLoaded(evt:Event):void { 
        var FontClass:Class
        if (evt.target.applicationDomain.hasDefinition(font1Name)) FontClass = evt.target.applicationDomain.getDefinition(font1Name) as Class;
        else if (evt.target.applicationDomain.hasDefinition(font2Name)) FontClass = evt.target.applicationDomain.getDefinition(font2Name) as Class;
        try {
            Font.registerFont(FontClass.myFont);
            trace("successfully loaded " + FontClass);
        } catch (err:Error) { 
            trace("couldn't register font "+FontClass.myFont+" =>"+err);
        }
    }  

The line in the embedded script about security is because of point #2: the registerFont doesn't work across domains. In fact the Security.allowDomain() didn't work and to debug this I have had to copy/paste the swf files on the PC and change the loader.load(URLRequest()) accordingly

There is still an issue that although the font is registered and claims to be compatible with the flash.text.engine TextElement requirements it still fails to be used as in:

        _tl = new Array();

        var block:TextBlock = new TextBlock();
        var font:FontDescription = new FontDescription(fontName);
        var formt:ElementFormat = new ElementFormat(font, fontSize);
//following gives 'true EnglishF'
trace(FontDescription.isFontCompatible(fontName,"normal","normal"), formt.fontDescription.fontName);
        formt.color = colr;
        var span:TextElement = new TextElement(text, formt);
        block.content = span;

        _tl[0] = null;
        _tl[0] = block.createTextLine(null, width);
        var tl:TextLine;
// after here justification and addition lines  

I will post something if and when I sort out why this doesn't work (Unless some kind person does it for me!)