ActionScript3で、TrueTypeフォントを外部swfにして動的に呼び出す

TTFをswfに埋め込む方法はmx:Styleなどを使えば簡単なのだが、例えば100種類フォントを使おうとするとひどく重いswfが出来上がってしまう。必要なフォントだけ動的にHTTP越しに取得できないかやってみた。

環境はFlex3。結果的に成功しましたが、ずいぶんややこしい実装になってしまいました。もっと簡単にやる方法があったら教えてくださいー。ActionScriptをいじるのは初めてなので思わぬ盲点がありそう。。

コードはcodereposに上げました。BSDライセンスで。
http://coderepos.org/share/browser/lang/actionscript/misc/myfont/trunk
svn checkout http://svn.coderepos.org/share/lang/actionscript/misc/myfont myfont


AS3で埋め込みフォントを使ってみる
出発点になったのが上記のページ。これだとswfをコンパイルしたときにTTFが埋め込まれ(TTF分のファイルサイズがswfに加わる)1つのフォントに1つクラスが出来上がる。100個作れば100のクラス名があるわけだが、まずそもそも任意のクラスをnewする方法がわからなかった。PHPだとこんな感じで複数あるクラスの中から1つをnewするのは簡単。

$className = 'anythingOK';
$c = new $className;

AS3では惜しいところまでいったのだが、コンパイルは通っても実行されない。下記のコメントアウトした方だとうまくいったがこれだとソースにハードコーディングせざるをえず、MyFontLabelの部分を動的に変えられない。

var classRef:Class = getDefinitionByName("MyFontLabel") as Class;
var myFont:Object = new classRef("hogehoge", 20);
//var myFont:Object = new classRef("hogehoge", 20) as MyFontLabel;

さらにもう1つ問題がある。外部swfにしたいクラスのメソッドを呼び出すコードが、親swfにあると、コンパイルしたときに外部swfのファイルサイズが親swfに加わってしまう。

基礎講座 SWFLoaderコントロール
がソースも見れてわかりやすい。
具体的にはここ。
LoadSWF(loadedSM.application).setInputData(input.text);
http://www.ebizsolution.jp/column/flex/src/SWFLoaderTest2.html

このsetInputDataはSWFLoaderで外部swfにしたクラス内に実装があるわけだが、コンパイル時に外部swfのasファイルが必須であり、呼び出し元のswfのファイルサイズが増えてしまう。フォントのように重いと外部swfにする意味がない。

八方塞がりかとも思われたが、同じソースの中の
loadedSM.application["indata"].text = input.text;
としている箇所は、コンパイル時にasファイルを要求されず、呼び出し元のswfのファイルサイズはそのままでいけた。出来上がったものも、これを使っている。

この辺り、僕が勘違いしているだけのような気もします。解決策ありそう。


さてここからはcodereposに上げたソースを元に。

app.mxml、FontListComboBox.mxmlはデモ用。MyFont.asが本体。binに前処理用のPHPスクリプト。

Top 100 | dafont.com
からダウンロードした約100個のフリーフォントを使っている。fontsディレクトリにTTFファイルを展開。

READMEにあるように、bin/makefontswf.phpを使って100個のswfを生成。asとmxmlの2つのファイルを生成してmxmlcでコンパイルしている。
やっつけでパスなどハードコーディングしてしまった箇所があるので適宜変えてください。あと、FreeFont_*.mxmlの、のXY座標をいい加減な位置にしているのとフォントサイズとカラーを指定できないのが気持ち悪い。this[‘indata’].textをXMLのように書式化してパースすれば後者の問題は解決するはず。

READMEの2行目のコマンドでデモ用に、bin/makefontlist.phpを使ってフォント一覧のComboBoxを生成するmxmlファイルを作っておく。

app.mxmlで呼び出しているMyFontクラスが本体。SWFLoaderを使って外部swfを呼び出し、application[“indata”].dataを書き換えることで外部swf(自動生成されたFreeFont_*.mxml)にあるdataChangeから内部のメソッドを呼び出す、という怪しげな手段を取っている。

ハマったのがMyFont.asの30行目のaddEventListener。最初はEvent.COMPLETEでやっていたのだが、コールバック関数内でloadedSM.applicationがnullだ、と怒られてしまう。Timerで無理矢理時間差を作れば動いたので、COMPLETE時にはswfの初期化がまだ終わっていないことが判明。APPLICATION_COMPLETEというイベントを発見して無事解決。

そんなこんなでコンパイルできたswfはこれ。テキストボックスに入れた文字列がComboBoxで選択中のフォントで表示される。フォントの関係で英字のみ。
http://zuzara.org/pub/myfont/app.swf

app.swf自体は233KBで各フォントは100〜1000KB。
swfはフォントごとに読みにいくようになっています。

AS3というよりActionScript自体初めてで結構苦労しました。。何に使うんだよ、という気もしますが参考になれば。

追記
高速にタイプするとchangeで呼び出しているメソッド内でエラーが出ます。解決策がわからない。。

This entry was posted in いじる. Bookmark the permalink. Both comments and trackbacks are currently closed.

3 Comments

  1. えんどー
    Posted 2008/02/27 at 9:30 pm | Permalink

    Flya用に、ちょうどテロップを作っていたのですが、
    この方法だと回避していた問題がクリアできちゃいそうです。

    日本語の場合、埋め込みたい部分的な所だけを動的に扱うのはどうなんでしょう?

  2. Posted 2008/02/28 at 11:04 am | Permalink

    ロードが終わるまでプログレスバーを出すなどの処理は必要そうですね。
    でもどうしても、でないならシステムフォントを使った方が軽くていいような気がします。

    あるいは元のTTFから常用漢字&サイズ限定で抽出して軽くできるとよさげです。

  3. Posted 2013/11/20 at 11:14 am | Permalink

    An impressive share! I have just forwarded this
    onto a colleague who has been doing a little homework oon this.
    And he in fact bought me lunch because I discovered it for him…
    lol. So allow me to reword this…. Thanks for the meal!!

    But yeah, thanks for spending the time to talk about this subject here on your web site.

    my web site; netticasino suomi

One Trackback

  • By candy crush saga life hack ipad on 2014/05/17 at 2:18 am

    candy crush saga life hack ipad

    ActionScript3で、TrueTypeフォントを外部swfにして動的に呼び出す

Page optimized by WP Minify WordPress Plugin