In een vorige post hadden we het over custom fonts en speciale karakters in Flash. Maar welke karakters embedden we nu best?
Bij het ontwikkelen van onze projecten houden we zoveel mogelijk rekening met de gebruiksvriendelijkheid. Het is dus niet meer dan logisch dat de eindgebruiker een website of applicatie voorgeschoteld krijgt in zijn of haar eigen taal, of tenminste een begrijpbare taal.
Voor sommige projecten vereist dit het ondersteunen van een ander alfabet, zoals bvb. het Cyrillisch of het Grieks.

Om karakters in een movie te embedden, hebben we in de Flash IDE (in dit geval de CS4 versie), een knop bij de eigenschappen van een tekstvak. Deze opent een venster waarbij we 1 of meerdere karaktersets kunnen aanduiden, of zelfs aparte karakters kunnen intikken die we mee willen embedden in onze file.
In dit venster kunnen we duidelijk zien welke karakters een bepaalde set omvat.
Als onze tekst echter in meerdere, vreemde talen moet getoond worden, is het soms onduidelijk welke karakter sets we juist moeten embedden. Om dit op te lossen kunnen we op deze website een XML bestand laten genereren, aan de hand van een tekstbestand waarin alle benodigde karakters staan.
Dit XML bestand kan gebruikt worden als UnicodeTable.xml, of kan de bestaande UnicodeTable.xml aanvullen (aan te raden). UnicodeTable.xml is een bestand dat door de Flash IDE gebruikt wordt, en dat alle karakter sets definieert die dan in het embed-venster komen (zie bovenstaande screenshot).
De door Flash gebruikte UnicodeTable.xml kun je op deze locatie terugvinden:
- Windows Vista:
<boot drive>\Users\<gebruiker>\AppData\Local\Adobe\Flash <versie>\<taal>\Configuration\FontEmbedding\
- Windows XP:
<boot drive>\Documents and Settings\<gebruiker>\Local Settings\Application Data\Adobe\Flash <versie>\<taal>\Configuration\FontEmbedding\
- Mac:
<boot drive>/<gebruiker>/Library/Application Support/Adobe/Flash <versie>/<taal>/Configuration/FontEmbedding/
Voor je UnicodeTable.xml wijzigt, neem je best een backup.
Zoals je kan zien staat elke karakterset in deze XML gedefinieerd, d.m.v. een node glyphRange. Deze node heeft 2 attributen, namelijk name en id. De id node wordt niet visueel getoond in de IDE, maar moet wel een unieke waarde bevatten. De waarde van de name node is wat we te zien krijgen in ons embed-venster, geef je eigen karakterset dus best een logische naam.
Welke tekens juist bij een bepaalde set horen kiezen we aan de hand van range nodes. Elke glyphRange node kan één of meerdere van die range nodes omvatten. Een range node definieert een tekenreeks, aan de hand van de <a href=”http://en.wikipedia.org/wiki/Unicode” title=”Unicode op Wikipedia”>unicode</a> waarde van het 1e en laatste karakter in die reeks. Als voorbeeld gebruiken we de voorgedefinieerde karakter set ‘Numerals [0..9]‘
<glyphRange name="Numerals [0..9] " id="3" >
<range min="0x0030" max ="0x0039" />
<range min="0x002E" max ="0x002E" />
</glyphRange>
Als we één van de vele unicode tabellen bekijken, kunnen we aflezen dat de unicode waarde 0x0030 het cijfer 0 voorstelt, 0x0039 staat voor het cijfer 9, en omdat we een range definieren zullen alle karakters tussen deze 2 ook binnen deze reeks vallen. Zoals we zien is het ook mogelijk om een enkel karakter als reeks te definiëren, dit gebeurt hier met de punt (.) die 0x002E als unicode waarde heeft.
Bij wijze van voorbeeld heb ik een karakterset gemaakt die ons Latijns alfabet met alle speciale tekens omvat, alsook het Cyrillisch en Grieks alfabet. De regels in commentaar zijn dubbele regels.
<glyphRange name="Latin Greek Cyrillic " id="27">
<!-- Uppercase [A..Z] -->
<range min="0x0020" max ="0x0020" />
<range min="0x0041" max ="0x005A" />
<!-- Lowercase [a..z] -->
<!-- <range min="0x0020" max ="0x0020" /> -->
<range min="0x0061" max ="0x007A" />
<!-- Numerals [0..9] -->
<range min="0x0030" max ="0x0039" />
<range min="0x002E" max ="0x002E" />
<!-- Punctuation [!@#%...] -->
<range min="0x0020" max ="0x002F" />
<range min="0x003A" max ="0x0040" />
<range min="0x005B" max ="0x0060" />
<range min="0x007B" max ="0x007E" />
<range min="0x02c6" max ="0x02c6" />
<range min="0x02dc" max ="0x02dc" />
<range min="0x2013" max ="0x2014" />
<range min="0x2018" max ="0x201a" />
<range min="0x201c" max ="0x201e" />
<range min="0x2020" max ="0x2022" />
<range min="0x2026" max ="0x2026" />
<range min="0x2030" max ="0x2030" />
<range min="0x2039" max ="0x203a" />
<range min="0x20ac" max ="0x20ac" />
<range min="0x2122" max ="0x2122" />
<!-- Basic Latin -->
<range min="0x0020" max ="0x002F" />
<range min="0x0030" max ="0x0039" />
<range min="0x003A" max ="0x0040" />
<range min="0x0041" max ="0x005A" />
<range min="0x005B" max ="0x0060" />
<range min="0x0061" max ="0x007A" />
<range min="0x007B" max ="0x007E" />
<!-- Latin I -->
<!-- <range min="0x0020" max ="0x0020" /> -->
<range min="0x00A1" max ="0x00FF" />
<range min="0x2000" max ="0x206F" />
<range min="0x20A0" max ="0x20CF" />
<range min="0x2100" max ="0x2183" />
<!-- Latin Extended A -->
<range min="0x0100" max ="0x01FF" />
<!-- <range min="0x2000" max ="0x206F" /> -->
<range min="0x20A0" max ="0x20CF" />
<range min="0x2100" max ="0x2183" />
<!-- Greek -->
<range min="0x0374" max ="0x03F2" />
<range min="0x1F00" max ="0x1FFE" />
<range min="0x2000" max ="0x206f" />
<range min="0x20A0" max ="0x20CF" />
<range min="0x2100" max ="0x2183" />
<!-- Cyrillic -->
<range min="0x0400" max ="0x04CE" />
<!-- <range min="0x2000" max ="0x206f" /> -->
<range min="0x20A0" max ="0x20CF" />
<range min="0x2100" max ="0x2183" />
</glyphRange>
Flash & custom fonts, het blijft een speciale combinatie. Op zich is een custom font gebruiken niet moeilijk, maar wat als je extended ASCII karakters wil gebruiken?
Bij de uitwerking van een Flash ActionScript 3 project voor Toyota Europe werd ons de vraag gesteld om ondersteuning te bieden voor andere talen, met hun eigen tekenset, zoals o.a. een Cyrillische tekenset. Zo gingen wij op zoek naar de meest efficiënte manier om een custom font te embedden, met ondersteuning voor de meer exotische karakters.
Fonts in de library
Een eerste, logische stap zou zijn om het gewenste font in onze Flash library op te slaan, en daaruit te exporteren.
Met het font in onze library kunnen we nu in de code duiken. We creëren een TextFormat object, waarin we de .name property invullen met de naam van ons font (de naam zoals je die ziet in elke tekst editor). Een goede manier om de naam van het font op te halen is via de Font.enumerateFonts() methode.
var fonts:Array = Font.enumerateFonts(false);
fonts.sortOn("fontName", Array.CASEINSENSITIVE);
var fmt:TextFormat = new TextFormat();
fmt.font = fonts[0].fontName; // Naam van het font als String
fmt.color = 0x4E3E16;
fmt.size = 20;
fmt.bold = false;
Om tekst te tonen hebben we natuurlijk een TextField nodig. Een overzicht van de belangrijkste properties.
var normalField:TextField = new TextField();
normalField.defaultTextFormat = fmt;
normalField.embedFonts = true;
normalField.text = "Custom font\n.text property\n&éèà# Ъ ē Ψ";
Als resultaat krijgen we volgende Flash movie. Het linkse veld is normale tekst, het rechtse html tekst.
Zoals je ziet worden de ‘gewone’ ASCII tekens en accenten getoond, de Cyrillische en Griekse tekens zijn echter in geen van beide gevallen zichtbaar.
[kml_flashembed fversion="9.0.0" movie="/wp-content/uploads/2009/01/as3-fontembedding-swf-01.swf" targetclass="flashmovie" publishmethod="dynamic" width="471" height="140"]
[/kml_flashembed]
Een font embedden in een tekstveld
Als we even terug de Flash IDE induiken, kunnen we een nieuw Flash AS3 bestand aanmaken. In dit bestand creëren we via de IDE een dynamisch tekstveld. In dit veld embedden we ons font via de ‘embed’-knop.

In ons geval embedden we de volgende karakter sets:
- Uppercase [A..Z]
- Lowercase [a..z]
- Numerals [0..9]
- Punctuation [!@#%...]
- Basic Latin
- Latin I
- Latin Extended A
- Greek
- Cyrillic
Als we tekst in dit tekstveld stoppen, zien we dat onze tekst getoond wordt, het font zit dus mee in onze movie.
Het zou natuurlijk nogal omslachtig zijn om per blok tekst een veld manueel op de stage te plaatsen. Een oplossing hiervoor is dat we ons tekstveld in een MovieClip stoppen. We hebben nu dus een MovieClip op onze stage, met daarin een TextField waarin ons font zit.
Deze MovieClip kunnen we nu van onze stage verwijderen, daar die toch nog in de library zit. Als we nu de MovieClip een klasse naam geven (bij de linkage eigenschappen) kunnen we deze exporteren.

Merk op dat ik de Sprite klasse als base class definieer, dit omdat we in deze ‘MovieClip’ geen gebruik maken van de timeline mogelijkheden.
Nu kunnen we ons font binnen onze applicatie gebruiken, mits we deze MovieClip 1x instantieren (zodat het font mee gecompileerd wordt).
new EmbeddedFont(); // Eénmalig instantieren
var field:TextField = new TextField();
field.embedFonts = true;
field.htmlText = "<font face=\"My Font\" size=\"20\" color=\"#4e3e16\">Custom font<br>.htmlText property<br>&éèà# Ъ ē Ψ</font>";
addChild(field);
Dit is echter niet praktisch, als we bijvoorbeeld meerdere SWF bestanden gebruiken zouden we telkens deze MovieClip moeten kopiëren naar elk FLA bestand. En wat dan als we helemaal geen FLA bestanden gebruiken om te compileren (bvb. via het Flex SDK)?
Een tekstveld in een SWC
Hoe kunnen we er nu voor zorgen dat we gemakkelijk aan onze geëxporteerde Sprite kunnen, zodat deze kan geinstantieerd worden? Via een centraal SWC bestand natuurlijk.
Bij de publicatie instellingen van onze FLA kunnen we er voor kiezen om deze Flash movie ook als SWC bestand exporteren.

Dit SWC bestand bevat dus onze Sprite met daarin het tekstveld en kunnen we voortaan gebruiken doorheen onze applicaties.
In ons voorbeeld hebben we de Sprite geëxporteerd als klasse EmbeddedFont. Nu kunnen we in een willekeurige Flash movie deze SWC integreren (via FDT kun je deze bijvoorbeeld aan je ’source folder’ toevoegen). De geëxporteerde klasse kan nu gebruikt worden in ons nieuw project.
Stel dat we in onze Flash applicatie een tekstveld willen, met daarin terug enkele speciale karakters, het enige wat we nu moeten doen is eenmalig een instantie aanmaken van onze geëxporteerde Sprite, zodat de compiler weet dat deze mee in de SWF moet.
Dan kunnen we doorheen alle klasses van de applicatie tekstvelden aanmaken, en ons font gebruiken.
new EmbeddedFont(); // Eénmalig instantieren
var field:TextField = new TextField();
field.embedFonts = true;
field.htmlText = "<font face=\"My Font\" size=\"20\" color=\"#4e3e16\">Custom font<br>.htmlText property<br>&éèà# Ъ ē Ψ</font>";
addChild(field);
Omdat we deze keer gebruik maken van de .htmlText property hoeven we hier geen TextFormat object aan te maken. Wil je gewoon de .text property gebruiken, dan werk je natuurlijk best wel met een TextFormat object.
Let erop dat we terug de naam van het font letterlijk moeten gebruiken, zoals je deze bijvoorbeeld in de Flash IDE ziet.
Links hebben we terug een tekstveld opgevuld via de .text property, links via de .htmlText property.
[kml_flashembed fversion="9.0.0" movie="/wp-content/uploads/2009/01/as3-fontembedding-swf-02.swf" targetclass="flashmovie" publishmethod="dynamic" width="471" height="140"]
[/kml_flashembed]
Meerdere SWF-files
Alles in orde zou je denken, maar wat dan als een applicatie meerdere SWF bestanden bevat?
Links hebben we hier een tekstveld binnen de SWF waarin we onze geëxporteerde EmbeddedFont klasse instantieren, het rechtse tekstveld zit in een SWF die bij runtime ingeladen wordt.
[kml_flashembed fversion="9.0.0" movie="/wp-content/uploads/2009/01/as3-fontembedding-swf-03.swf" targetclass="flashmovie" publishmethod="dynamic" width="471" height="140"]
[/kml_flashembed]
Ons font wordt dus niet getoond doorheen alle SWF bestanden.
Doordat we met een SWC bestand werken waarin ons font vervat zit, kunnen we dit gemakkelijk oplossen. Een gemakkelijke manier is om gewoon binnen elk SWF bestand, onze geëxporteerde klasse één maal te importeren.
In onderstaand voorbeeld hebben we terug een SWF bestand, met links een tekstveld, en rechts een ingeladen SWF bestand met ook een tekstveld. In beide SWF bestanden wordt onze klasse 1x geinstantieerd, en nu worden alle tekens getoond.
[kml_flashembed fversion="9.0.0" movie="/wp-content/uploads/2009/01/as3-fontembedding-swf-04.swf" targetclass="flashmovie" publishmethod="dynamic" width="471" height="140"]
[/kml_flashembed]
Conclusie
Er zijn natuurlijk meerdere manieren om fonts te gebruiken binnen Flash, en elke manier heeft zijn voor- en nadelen. Uit ervaring merken wij echter dat deze manier weinig omslachtig en zeer flexibel is. Ook vooral de ondersteuning van allerhande tekensets naar wens zorgt ervoor dat deze implementatie gemakkelijk werkt.