W.Deeの2005年10月の日記

kikyou.info»日記
最新月 : 2008年10月
2003年 [             3    4    5    6    7    8    9   10   11   12  ] 月
2004年 [   1    2    3    4    5    6    7    8    9   10   11   12  ] 月
2005年 [   1    2    3    4    5    6    7    8    9   10   11   12  ] 月
2006年 [   1    2    3    4    5    6    7    8    9   10   11   12  ] 月
2007年 [   1    2    3    4    5    6    7    8    9   10   11   12  ] 月
2008年 [   1    2    3    4    5    6    7    8    9   10   11   12  ] 月
2009年 [   1    2    3    4    5    6    7    8    9   10   11       ] 月
前月の日記  次月の日記

2005年10月29日

ヒンティング

 画面のような解像度の低いデバイスに文字を描画する際、文字の垂直線や水平線(ステム)をピクセルの境界に合わせる(グリッド・フィット)という処理(ヒンティング)があります。

 ヒンティングを行った文字(左)と行わなかった文字(右)を比較すると以下のようになります。

ヒンティングを行った'M'文字ヒンティングを行わなかった'M'文字

 ヒンティングを行わないとこのようにぼけて表示されてしまい、かなり見づらい物となってしまいます。

 TrueTypeなどの場合、一文字一文字に対してこのヒンティングを行うための処理を行うためのプログラムを持つことができ、この処理のために(実際はもっといろいろできるようですが)、TrueType のラスタライザはバイトコードインタプリタ(仮想マシン)を持っています。

 「JSP明朝」などは日本語フォントですが、かなり綺麗なヒンティングを行ってくれるようです。以下はこのフォントでの64px高さの「廊」の下の部分です。このイメージではグリッド線を描いてありますが、グリッドの境界にぴったりと垂直線や水平線が収まっているのが分かると思います。

「JSP明朝」の「廊」の下の部分

で、64pxぐらいだと綺麗なのですが、画数の多い漢字では24pxぐらいだとヒンティングが仇になることがあるようです。

以下は「JSPゴシック」でヒンティングを行った場合です。

「JSPゴシック」でヒンティングを行った場合

線と線がくっついて文字がつぶれてしまっていますね。

ちなみに上記は FreeType でのラスタライズ結果ですが、GDI にやらせるとこんな感じです (GDIはヒンティングを行う)。

GDIで描画した「JSP」ゴシック(ヒンティングが行われている)

FreeType にはヒンティングを行わせないオプションが有るのですが、ヒンティングを行わないと以下のようになります。

「JSPゴシック」でヒンティングを行わなかった場合

ボケてますが、線と線がくっついているよりは読みやすい印象を受けませんか。

大体のTrueTypeフォントでは、これぐらい (24pxとか28pxぐらい) のフォントだとヒンティングを行わない方が読みやすい印象を受けるため、これぐらいのサイズだったらヒンティングを切ってしまえ!と思ったのですが、妙なフォントがあります。

これは「DF平成ゴシック」を24px高さでヒンティングを行った場合。

「DF平成ゴシック」を24px高さでヒンティングを行った場合

ヒンティングを行わなかった場合。

「DF平成ゴシック」を24px高さでヒンティングを行わなかった場合

とても手書き風の崩れた文字となってしまっています。

たぶんこのフォントはここに説明があるような「TrueType bytecode interpreter を有効にしてコンパイルすると、 DynaFont (合成文字タイプ) に autohinter を適用しても読める文字を出力できます。」に該当する「合成文字タイプ」なんじゃないかと思います。たしかに bytecode interpreter 無効にすると同じような崩れ方をするので。

というわけで、このように変になるフォントがあるので、一括してヒンティングをオフにできません。どのフォントでヒンティングを行わないとおかしくなるかはフォント名との対応表を持ってないと難しそうです。

吉里吉里3は一応文字描画時のフォントオブジェクトのプロパティとしてヒンティングを行うかどうかのフラグを持たせるようにしますから、ユーザに綺麗に表示される方を選んでもらうとかいった対策が必要になるのかも知れませんし、「キニシナイ」のも一考かもしれません。

部品買いに行こう

秋葉原に部品買いに行きます ...

2005年10月28日

メインマシンが壊れた

まいりました。

動かしていると勝手に再起動したり電源が落ちたりします。たぶん電源ユニットまわりかと。

電源だけ付け替えるって手もあるけど、それにしても結構長く使ってるから買い換えかなーとか。

デュアルコアOpteronあたりにダイブしてみたいです。

それまではノート PC で開発かな。

2005年10月23日

開発者向けサイト立ち上げました

上記のメーリングリストでの話題のまとめや開発方針、バグ追跡、リポジトリ閲覧のために開発者向けサイトを立ち上げました。

このサイトはTracを使って構成されています。Subversion との同期や wiki との統合などの機能を持った、Webベースのプロジェクト管理ソフトウェアです。

ただ、自分もこういうソフトウェアを使ってサイトを立ち上げるのは初めてですから、よく勉強しないと。とりあえず立ち上げたというだけです。一応リポジトリはオンラインで見られるようになってますし、リポジトリへのコミットなどを RSS で受け取ったり、吉里吉里の Subversion リポジトリに書き込み権限を持っていらっしゃる方ならばログインすることによってページを編集したりできます。

開発者向けメーリングリスト立ち上げました

kikyou.info に mailman を導入し、開発者向けメーリングリスト を 立ち上げました。kikyou.info にあるメーリングリストの一覧はこちら。といってもまだ1つしか有りませんけど。

参加は自由です。

そのページに「KAGの使用方法やTJSによるプログラミングの一般的な質問は、吉里吉里掲示板をご利用ください」と書いてありますが、単発的な質問は、開放的で書き込みやすい掲示板の方が向いていると考えているからです。

対して、開発に関する話題は、議論が始まるとスレッドが長大になる傾向が有るので、ML の方が適していると考えています。

2005年10月19日

機能とバイナリサイズのトレードオフ

それにしても全体の1%、もしかしたら1%未満の人しか使わない機能のために、バイナリサイズをでかくしてまでそれを盛り込むかというのは難しい問題ですね。これがサウンド形式とかのような結構上層の問題ならばあきらめが効くのですが、文字コードの扱いという、かなり土台の話なのでしっかり作っておかないとな、と思います。

そういう基本的な機能はちゃんとOSがサポートしてくれればいいのですが…。

まあ最近PCはメディアも高速回線も普及してるから、とは思うのですが。吉里吉里2がすぐになくなるというわけでもないですし。

Boost.Regex

吉里吉里2で使ってる Boost.Regex ですが、久しぶりに見に行ったら ICU を用いて Unicode 完全サポートとか書いてあります。

…もうこの際 ICU でもなんでものっけるかな。ICUってたしかバイナリが10MBぐらいあったような。ICUライブラリのなかで一番大きいのはそのデータですが、結構要らないテーブルも入ってるし、要らないテーブルはコンパイル時に はずせるようなので、ダイエットはできそう。

吉里吉里3は UTF-32 ベースに

吉里吉里2は UCS-2 ベース (UTF-16を扱うことは考慮してません) だったのですが、吉里吉里3は UTF-32 ベースにしようかと思います。

理由は吉里吉里3が対象にしそうなプラットフォーム (Linux, MacOS X, Windows) のうち、wchar_t のサイズが、Windows だけが 2 バイトで 他が 4 バイトだからです。ちなみに Solaris も 4 バイト。MacOS X と Linux については wchar_t は UTF-32 を扱ってたと思います (Solaris は wchar_t が扱う文字コードは主にUCS-4 ? というだけで特に規定してなかったと思うけど間違ってたらごめんなさい) 。

と言うわけで Windowsだけが UTF-16 なのがイヤという理由で UTF-32 にします。通常の使用を考えれば UTF-16 で極めて十分なのかも知れませんが、どうせ UTF-32 にしたって1文字≠1コードポイントという扱いは変わらないわけだし、最近のコンピュータはパワーがあるし、テキストデータの量なんて画像データや音声データに比べれば微々たるものだと思います。

  • 2005-10-22 23:09 Dreamwoods : 開発の自由度が奪われる方向への発展ですね。UTF-32を本気で導入する気ならテキストエディタ同梱が必須です。
  • 2005-10-23 00:08 W.Dee : いやいや 内部文字コードの話です
フォント周り作成中

吉里吉里3となるべきプログラムのフォント周りをちまちまと作っています。

文字描画周りはフォントドライバという形でいくつかのフォント描画バックエンドを扱えるようにする形で書いています。今のところ使用可能なバックエンドは、TTF/OTFを扱うFreeTypeドライバと、レンダリング済みフォント作成ツールが生成したビットマップフォントを扱うドライバを考えています。FreeType ドライバで扱えないような(たとえば BIG5 エンコーディングは今のところ未サポート) フォントを扱うために、Windows の GDI を使って文字を描画する GDI ドライバも必要かなと思っていましたが、いまのところ FreeType で問題なさそうなので作らない予定で。

FreeTypeドライバの方はだんだんとできあがってきています。手持ちの(記号類を除く)フォントは全部表示できるようになりました。

レンダリング済みフォント作成ツールも同じフォントドライバを使って描画してますが、そのフォント プレビュー画面はこんな感じです。

レンダリング済みフォント作成ツールプレビュー画面

ちなみに左端の文字は U+02146E に割り当てられている文字です。フォントが対応していれば U+010000 以上 (BMP以外) に割り当てられている文字も扱うことができます。まあ普通は使わないと思うのですが。

2005年10月10日

FreeTypeでWindowsフォントを使用する

FreeTypeはフォントファイルに直接アクセスをします。Windowsプラットフォームの場合は、Windowsプラットフォーム上のアプリケーションが通常使う GDI を使用しないという事になります。

吉里吉里の場合、ユーザに好きなフォントを選択させる用途が少なからずあるので、システムで使用可能なフォントを列挙する必要があります。FreeType が GDI を使用しないからと言って、使用可能なフォント名の列挙を GDI を介さずに行おうとすると、全てのフォントファイルを開いてフォント名を取得しなければなりません。

TrueType フォントファイルの中に入ってるフォント名を取得する方法は、確たる仕様が無いためか現実的にはめちゃくちゃです。TrueType フォントはプラットフォーム (MacかMicrosoftか) ごとや言語、エンコーディングごとに該当するフォント名を持つことが出来るようになっているのですが、MSプラットフォームでSJIS でエンコーディングされていると指定されているにもかかわらずにUCS-2BEでフォント名が入っていたり(というかSJISエンコーディングでSJISでフォント名が格納されているフォントを見たことがない)、ヒドイのになるとMacプラットフォームなのに言語IDにMicrosoftの物が入っていたり、言語名が英語なのにもかかわらずにSJISでフォント名が入っていたりと、めちゃくちゃなのにも程があります。

それにフォントファイルを全て開いてフォント名を取得するのは、フォントが5~6個ならばすぐですが、最近のシステムだと100個ぐらい入ってても不思議ではないので、時間がかかります。自分の開発用マシンは (TrueType以外も含めて) 261 個フォントファイルが入ってますが、この方法でフォントファイルを列挙しようとすると1分ぐらいかかります。

GDI はたぶんシステムの起動時に全てのフォントファイルを開いてフォント名を列挙して、システムが立ち上がっている間はそれを使っているようです。まあフォント名の列挙ぐらいはそれを使かおうかと。

ただ、GDI が列挙するフォント名 ("MS Pゴシック"とか) からフォントファイル名を得る方法は、どこを探しても見あたりません。レジストリ HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts に格納されているのは分かるのですが、そこのレジストリの形式もドキュメント化された仕様が見つかりません。

フォントファイル名を知る方法は安全な方法がないようなのですが、フォントファイル自体にはアクセスする方法があります。TrueType/OpenType のフォントに GDI 経由でアクセスするには GetFontData API を使用します。

GDI で デバイスコンテキストにフォントを選択した後、そこの説明にあるように、dwTable と cbData に 0 を指定すると フォントファイルのサイズが分かります。あとは、dwTable に 0 を指定したまま、dwOffset でフォントファイルの先頭からのオフセット、lpvBuffer にデータを格納したいバッファ、cbData に読み出したい長さを指定すれば、フォントに直接アクセスすることが出来ます。あとはFreeTypeで使用可能になるように、FreeType用のストリームの実装をしてやればよいと言うことになります。

この方法には落とし穴があって、TTC (TrueType Collection) フォントに対しては正しく動作しません。dwTableに 0を指定しても、TTCファイルの4バイト目からの読み出ししか出来ないのです。この場合は、dwTable に0x66637474を指定する とファイル全体に関する情報を得ることが出来ます ( 0x66637474 = 'ttcf' )。コレに関してはMicorosoftの中の人が否定してないというかなんか気持ち悪いほどほめてるので問題ないと思います。

ただし、まだまだやらなければならないことがあります。TTCファイルは複数のフォント名を含んでいます。上記の方法で TTC ファイル全体へのアクセスは出来るようになりましたが、「その TTC ファイル内のどのフォントか」がまだ分からないままです。ここでまた GetFontData を使います。GetFontData で TTC フォントに対して dwTable に 'name' のような、フォントごとに異なる情報を持つテーブルを指定すると、TTC ファイル内の各フォントに対応した情報を返してきます。これを、FreeType が返す同種の情報を比較してやることで、TTC ファイル内のどのフォントが対応しているかを探すことが出来ます。FreeType の Face を開く FT_Open_Face 関数の index 引数に 0 から順に数字を指定していって、この情報が一致する index が、TTCファイル内の該当するフォントの index であるということになります。FreeType 側の対応する関数は FT_Load_Sfnt_Table です。

TrueType/OpenType フォント以外は対応しなくてもとりあえずはよいかな、と。実際吉里吉里2でも対応はしてませんし。

とりあえずここら辺の動作を記述したC++ソースファイルはこちら。まだ作りかけなので不完全かも知れませんが参考になれば。

しかしこの方法に至るまでに1週間以上費やした orz

他プラットフォームはどうなのかはまだよく調べてません。

2005年10月5日

Theoraを標準に

吉里吉里3での動画コーデックの標準をTheoraにすることを計画しています。

MPEG系は特許の問題が絡むので、特許の心配が無く、コーデックがフリーで入手できるTheoraは、エンジンの制作者側としては魅力的な選択肢となります。

私はあまり動画制作には詳しくないのですが、これを標準に据えた場合、どんな影響があるんでしょうか。制作環境(ツール)の不足がまずネックになるような気がします。

標準に据えるというだけなのでとりあえず他のコーデックも積めるような構造にしておきたいとは思っています。

圧縮率は MPEG-4 と同等か、より高いと言われています (参考 : Wikipedia:Theora)。

現在のSDK最新版はalpha5で、まだ最適化などが不十分という話ですが、吉里吉里3がまともに動き始めるまでの間にはなんとかなってると思います (とは言ってもTheoraの1.0が出るのって予定では相当昔だったような )。

Theora動画の作成や再生などについては、[妖精現実 フェアリアル]Windows で Ogg Theora などが参考になります。再生は VLC media playerなどが対応しています。

Theoraのオフィシャルなライブラリである libtheora はただのコーデックですので、それを画面に表示したり音声との同期をとるなどと言うのはまた別の話になります。画面表示や音声再生はプラットフォームに強く依存する部分ですので、上記の VLC などを参考にしてこちらで書き起こすか、適当なライブラリがあればそれを使おうと思います。

そういえば Dirac という手も...こっちはこっちでどうなってるのか調べないと。

あと楓Softwareさんのところで開発が続けられている吉里吉里ムービー拡張とのかねあいも。

Eclipse CDT 再び

Eclipse CDT には Makefile を自分で書いてビルドする方法と、Eclipse にビルド管理をさせる2つの方法が有るようです。最初は CDT に管理をさせていましたが、xgettext や XRC の変換など、ビルドの方法が複雑になってくるとどうやって管理させたらよいのかが分からなくなってきたので、結局自分で Makefile を書き始めました。

JRE を IBM 製にしたおかげで Indexer がハングアップすることは無くなりましたが、やっぱり補完は重い。重い上に wxWidgets のヘッダファイル内にあるシンボルをうまく拾ってくれない気がします。うっかり -> とか打った後うっかり次のタイピングを始めないと、20 秒ぐらい固まるハメになります。解決方法が見つかるまで補完はオフにしようかな。

デバッガはこんな感じです。

CDTデバッガ

こっちもブレークポイントを指定した位置でちゃんと止まってくれなかったり、なんとなく不安定な印象。

たぶん使っていくうちに慣れるだろうということで、しばらく Eclipse CDT を使っていこうかなと思っています。

国際化

といってもとりあえずメッセージの置き換えですが、wxWidgets は gettext 方式のメッセージ置き換えに対応しています ( gettext memo などが参考になります )。

ここを参考にして適当に mo ファイルを作成。割と簡単に日本語化が出来ました。

上記スクリーンショットでダイアログボックスの中身が日本語になっているのもこの方法でメッセージの置き換えをやっています。XRC リソース中の文字列は、XRC リソースから xgettext が認識可能な形でメッセージを抽出する機能が wxrc にあるのでそれを使います。

とりあえず英語でメッセージを作っておいて、日本語メッセージはあとからそれらを翻訳する形で作っていこうかと思っています。

XRCed を使う

前回 wx-DevCpp を使ってみたのですが、今度は XRCed を使ってみました。

XRCed は wxWidgets の Python バインディングである wxPython の付属ツールのようですが、XRC 形式のファイルをはき出すだけなので、C++での開発にも使えます。

XRC とはなんぞやということですが、XML で記述されたリソース形式で、言語やプラットフォームに依存しないのが特徴のようです。C++ 形式には wxrc という付属ツールで変換することが出来ます。

とりあえず使用中のスクリーンショット。フォントメトリクスを生成させるツールが必要だと言うことで、レンダリング済みフォント作成ツールを wxWidgets + FreeType を使って作り直す事にしました。FreeType がOSを介さずにフォントファイルへのアクセスを必要とする関連で完全にマルチプラットフォームというわけにはいかないのですが ...

XRCedを使用中

sizer は使っていくうちに慣れました。概念としてはHTMLのテーブルに近くて、内容の大きさによって外形を伸縮させたり、逆に外形の伸縮に従って内容を伸縮させたりが出来ます。wxWidgets は基本的にプラットフォームごとにネイティブなwidgetを使用するので、プラットフォームごとに違うwidgetのサイズにも、特に意識をせずに対応することが可能と言うことになります。

sizer はレイアウトに合わせて種類を変えたり、入れ子にしたりしますが、どのような構造にすればよいかは、使っていくうちに簡単に思いつくようになります。

sizerを使ったコントロールの伸縮の例

スタティックテキスト(ラベル)やチェックボックスのラベルも、上図のように内容に応じて自動的に伸縮するので、内容の翻訳をしても文字が切れて読めなくなるような事はありません。