Es macht Sinn, verwendete Schriftarten in eine Flashanwendung einzubinden – so sind sie unabhängig vom Zielsystem verfügbar, und nicht zuletzt kann man erst dann (Alpha-)Tweens auf sie anwenden. Andererseits machen sie die Flashanwendung zum Teil sehr groß. Die Lösung? Die Schriftarten erstmal in eine separate SWF auslagern:
1 2 3 4 5 6 7 8 9 10 |
package x.y.z { import flash.display.Sprite; public class Fonts extends Sprite { [Embed(systemFont='Arial', fontName="Foo", fontWeight='bold', mimeType='application/x-font')] public static var Foo : Class; } } |
Zu beachten: Die Klasse muss Sprite extenden; der FontName sollte ein anderer sein als der Fontname im System (um diesen nicht zu überdecken); Schriftschnitte wie bold oder italic müssen explizit eingebunden werden. Der Übersichtlichkeit halber benenne ich die Fonts (FontName) genauso wie die Klasse, in die sie embedded werden (hier: “Foo”)
Diese Klasse wird nun kompiliert, und die SWF unter einem Pfad, zB “fonts.swf” abgelegt. Unter diesem Pfad kann sie nun, etwa im Rahmen einer Preloader-Queue mit weiteren Assets, dynamisch von der eigentlichen SWF nachgeladen werden:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
private var _loader:Loader; private function loadFonts():void { _loader = new Loader(); _loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress); _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete); _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIoError); _loader.load("fonts.swf", new LoaderContext(false, ApplicationDomain.currentDomain)); } private function onIoError( error:IOErrorEvent ):void { // handle error } private function onProgress( event:ProgressEvent ):void { // display progress } private function onComplete( event:Event ):void { var AssetClass:Class = Class(ApplicationDomain.currentDomain.getDefinition("x.y.z.Fonts")); Font.registerFont( AssetClass["Foo"] ); } |
Zu beachten hierbei: Es muss der komplette Package-Pfad (“x.y.z.Fonts”) an ApplicationDomain.getDefinition() übergeben werden! Nur der Klassenname genügt nicht.
Außerdem: Wann immer man den Text des entsprechenden TextField (neu) gesetzt hat, muss das TextFormat mit dem eingebundenen Font (neu) zugewiesen werden. Die Property embedFonts setzt man auf true:
1 2 3 |
tf.text = "Some text"; tf.embedFonts = true; tf.setTextFormat( new TextFormat("Foo") ); |
hth.
oder meinen FontManager.as benutzen, die sourcen haste ja noch vom glk projekt 🙂
Soweit ich den verstanden habe, muss ich die Fonts aber auch erstmal geladen haben 🙂 hier würde er also die onComplete() ersetzen…
das Ziel hier war, die Fonts im Rahmen *einer* Loading-Queue mit 20 anderen Assets verschiedensten Typs zusammen vorzuladen; hier habe ich nur den Font-Teil der Preloader-Logik gepostet. Was man nun machen kann, ist den Loader auszulagern, und ein eigenes PreloaderItem zu schreiben, das auch einen Callback (quasi ein spezifisches onComplete()) enthält. Nun kannst Du Grafiken laden, die über den enstprechenden Callback verarbeiten; und die Fonts-SWF über einen anderen Callback an die Font.registerFont übergeben. Trotzdem behälst Du *eine* Queue, und damit auch *eine* Fortschrittsanzeige. Hm, hat das eigentlich noch was mit Deinem Comment zu tun? Ich glaube nicht 🙂
PS: Die Grafik kommt aus den TextLineMetrics:
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/text/TextLineMetrics.html