Archive for February, 2008

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

Feb 27 2008 Published by funaki under いじる

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で呼び出しているメソッド内でエラーが出ます。解決策がわからない。。

2 responses so far

PHPでSQLiteに書き込もうとしてGeneral error: 14 unable to open database file が出たときの対処

Feb 15 2008 Published by funaki under いじる

PHP5.2.5でPDOからSQLiteに普通にINSERTしようとしたとき、
Warning: SQLSTATE[HY000]: General error: 14 unable to open database file ...
とエラーが出て困った。SELECTは問題なくできる。

SQLiteのファイルのパーミッションが644だったりすると
Warning: SQLSTATE[HY000]: General error: 8 attempt to write a readonly database
というエラーが出るのだが、666にしてあったのでこれではない。

結論としては、SQLiteのファイルを置いたディレクトリに書き込み権限が必要だった。(apacheの実行ユーザとかの)
下記のページを見て解決したのだが特にバグ、というわけでもないらしい。
[sqlite] Problems with SQLite and PHP
Re: [sqlite] Problems with SQLite and PHP

SQLite needs to be able to create and delete a journal file during
database modification.

マニュアルのコメントにも載っていた。
PHP: SQLite – Manual

いずれにせよ、unable to open database fileというのは不親切なエラーメッセージだと思う。

PHPのソースコードをちょっと追ってみた。
ext/pdo_sqlite/sqlite/src/os_unix.c
を書き換えればいいのかな?
実際にエラーが起きている箇所を特定できなかったが、sqlite3UnixOpenExclusive()だろうか。/var/tmp内にテンポラリファイルは開きそうなコードなのだがこのディレクトリは777でも関係なかった。sqlite3UnixTempFileName()にあるsqlite3_temp_directoryがなんなのかわからず。

No responses yet