YS SYSTEM FONT Library for Windows, MacOSX, and Linux (X-Window)

Updates
  2011/05/13 公開



1. 概要
このパッケージは、Windows, MacOSX, Linux (X-Window)上で共通に利用可能なC++フ
ォントビットマップ展開コードを提供する。多分、MacOSX用コードで、そのままiOS用
に使えると思うけど、まだ試してない。

OpenGLの最大の弱点のひとつが、字が書けないってことだ。フォントの管理とグラ
フィックスを分離するっていう判断は、理屈としては正しいかもしらんけど、プロ
グラム書く方にしてみると、とにかくなんでもいいから字を出したいってときに、
かなり困る。wglUseFontBitmapとかを使えば、アスキー文字は出せるけど、漢字は
出ない上に、Windowsに依存してしまって、せっかくクロスプラットフォームなOpenGL
の意味がまったくない。OpenGLは、たかが字を書こうとしただけでプラットフォーム
に依存してしまうのだ。これは十分弱点と言えると思う。

それで、アスキーコードだけだったら、プログラム内部にフォントを持たせてしま
えばプラットフォームに依存しなくなるからってことで、アスキー文字だけ表示で
きるようにするコードを前に公開したけど、漢字は出なかった。

多言語に対応するために、Unicodeのフォントのデータを自分のプログラムのパッケ
ージに組み込むなんてことをしたらパッケージのサイズが巨大化してしまう。それ
じゃあ、「このプログラムを利用するには、こういうフォントをここからダウンロ
ードしてきて、このディレクトリに置いてください」というような説明をつけて出
すことはしたくない。だって、プログラムダウンロードするとき、ファイル一本に
全部入っていてくれる方が楽でいい。それに、必要なデータファイルは、サイトが
移転したり閉鎖したりで、同じ場所からダウンロードできなくなってみたりする。

せっかくWindowsなりMacOSXなりLinuxなりシステムがUnicodeに対応したフォントを
持ってるんだから、それを利用した方がいい。が、問題は、フォントのビットマップ
にアクセスするには、それぞれのPCでてんでんばらばらのAPIを使わなきゃならない
ってことだった。漢字を出すたびにプラットフォームごとに違うコードを書いてると
あまりにも非能率的だ。

なので、とりあえず、WindowsとMac OSXとLinux (X-Window)で共通に使えるC++フォ
ントビットマップ展開コードを作ることにした。コンセプトは、フォント名とか指
定できなくていいから、指定の大きさで、とにかく簡単なコードで読める文字を出
すこと。





2. ヘッダファイル、ソースファイル
このコードを利用するには、yssystemfont.hをインクルードする必要がある。なの
で、yssystemfont.hをインクルードパスが通ったディレクトリにコピーするか、ま
たは、yssystemfont.hのディレクトリにインクルードパスを追加しておく必要があ
る。

また、ライブラリの形式にするまでも無いと思ったんで、そのままソースファイル
がsrcディレクトリ下にあるので、それぞれ、

    MacOSX用
        src/macosx/ysmacosxsystemfont.cpp
        src/macosx/ysmacosxsystemfont_objc.m

    Windows用
        src/windows/yswin32systemfont.cpp

    Linux用
        src/linux/ysunixsystemfont.cpp

を、利用するアプリケーションと一緒にコンパイルしてリンクする必要がある。





3. 大雑把な使い方
ビットマップを展開するために、次の二種類のクラスを使う。

    YsSystemFontCache
    YsSystemFontTextBitmap

YsSystemFontCacheは、プラットフォーム依存のデータ（ハンドルだったりグラ
フィックスコンテキストだったりディスプレイポインタだったり）を内部で隠蔽し
て、フォントビットマップを展開する機能を持つ。このクラスの関数

    YsSystemFontCache::MakeSingleBitBitmap
    YsSystemFontCache::MakeRGBABitmap
    YsSystemFontCache::MakeGrayScaleAndAlphaBitmap

のうちのひとつを使って、YsSystemFontTextBitmapにビットマップを展開するこ
とができる。展開したビットマップは、ほとんどそのままOpenGLのglDrawPixels
かglBitmapで描画することができる。(glDrawPixelsは(24ビット＋α)/pixel、
または、(8ビット＋α)/pixelのとき、glBitmapは1ビット/ピクセルのとき)

ただし、YsSystemFontCacheの生成は結構重くて、また、ビットマップの展開も
結構遅い。なので、決まった文字列を何度も描画するときは、あらかじめビット
マップを展開しておいた方が良い。ビットマップを展開した後なら、
YsSystemFontCacheは無くてもいい。

例えば、次のように生成したビットマップに対して、

    YsSystemFontCache fontCache;
    fontCache.RequestDefaultFontWithHeight(20);

    YsSystemFontTextBitmap bmp1,bmp2,bmp3;
    wchar_t yamakawa[]={0x5c71,0x5ddd,'\n','Y','a','m','a','k','a','w','a',0};
    wchar_t soji[]={0x7dcf,0x53f8,'\n','S','o','j','i',0};
    wchar_t greek[]={0x03b8,'=',0x03c0,0x03c9,0};

    fontCache.MakeRGBABitmap(bmp1,yamakawa,0xffffff,0,YSTRUE);
    fontCache.MakeSingleBitBitmap(bmp2,soji,YSTRUE);
    fontCache.MakeGrayScaleAndAlphaBitmap(bmp3,greek,0xff,0,YSTRUE);

次のOpenGL関数で描画が可能。

    glRasterPos2i(0,bmp1.Height()-1);
    glDrawPixels(bmp1.Width(),bmp1.Height(),GL_RGBA,GL_UNSIGNED_BYTE,bmp1.Bitmap());

    glColor3ub(0,255,0);
    glRasterPos2i(0,bmp1.Height()+bmp2.Height()-1);
    glBitmap(bmp2.Width(),bmp2.Height(),0,0,bmp2.Width(),0,bmp2.Bitmap());

    glRasterPos2i(0,bmp1.Height()+bmp2.Height()+bmp3.Height()-1);
    glDrawPixels(bmp3.Width(),bmp3.Height(),GL_LUMINANCE_ALPHA,GL_UNSIGNED_BYTE,bmp3.Bitmap());





4. タイプ、クラス

typedef enum {YSERR,YSOK} YSRESULT;
  実行結果を表すタイプ。



typedef enum {YSFALSE,YSTRUE,YSTFUNKNOWN} YSBOOL;
  真偽を表すタイプ。



YsSystemFontTextBitmapクラス
  フォントを展開した結果を保持するクラス。YsSystemFontCacheクラスが生成する
  フォントビットマップを内部に保持する。
  [メンバ]
    inline YsSystemFontTextBitmap();
      デフォルトコンストラクタ。

    inline ~YsSystemFontTextBitmap();
      デフォルトデストラクタ。YsSystemFontCacheクラスが生成したビットマップ
      をこのオブジェクトが保持していた場合は、ビットマップが使用していたメモ
      リ空間を解放する。

    inline void CleanUp(void);
      中身を空にする。

    inline unsigned int Width(void) const;
      横ピクセル数。

    inline unsigned int Height(void) const;
      縦ピクセル数。

    inline unsigned int BytePerLine(void) const;
      横一列あたりのバイト数。

    inline unsigned int BitPerPixel(void) const;
      一ピクセルあたりのビット数。

    inline const unsigned char *Bitmap(void) const;
      ビットマップデータを返す。

    inline unsigned char *TransferBitmap(void) const;
      ビットマップデータの管理を他のクラスに移管する。

      オブジェクトがビットマップデータを保持した状態で、この関数を実行する
      と、ビットマップデータへのポインタを返して、このオブジェクト自身は空
      のビットマップになる。（そうでない場合はNULLを返す。）

      この関数が返すポインタは、以後このオブジェクトの管理下ではなくなるの
      で、デストラクタはこのポインタが指し示すメモリブロックを解放しない。
      なので、このビットマップが不要になったとき、呼び出し側でdelete []を
      使って削除する必要がある。

      YsSystemFontTextBitmapクラスを使ってビットマップを作った後、別のデー
      タ構造にビットマップを管理させたいとき、この関数を使うことで、ビット
      マップのコピーによるオーバーヘッドを回避できる。



YsSystemFontCacheクラス
  フォントビットマップを展開する機能を持つ。
  [メンバ]
  YsSystemFontCache();
    デフォルトコンストラクタ。デフォルトフォント（あるいは、多分デフォルトに
    一番近いと思われるフォント）を使用できる状態に初期化する。

  ~YsSystemFontCache();
    デストラクタ。


  YSRESULT RequestDefaultFont(void);
    デフォルト（または多分デフォルトに一番近そうな）フォントのビットマップを
    生成できる状態にする。


  YSRESULT RequestDefaultFontWithHeight(int height);
    デフォルト（または多分デフォルトに一番近そうな）フォントに高さを指定して
    ビットマップを生成できる状態にする。


  inline YSRESULT MakeRGBABitmap(
      YsSystemFontTextBitmap &bmp,
      const wchar_t wStr[],unsigned 
      int fgCol,const unsigned int bgCol,YSBOOL reverse) const;
    UNICODE文字列wStrを表すビットマップを生成してbmpにビットマップを返す。
    fgCol, bgColは、24ビットカラーコードで0xRRGGBBフォーマット。

    reverseにYSFALSEを指定すると、メモリブロックの先頭がビットマップの上端
    に対応する。

    glDrawPixelsでビットマップを表示するときは、メモリブロックの先頭が最下
    端に対応するので、reverseにYSTRUEを指定する。（そうでないと上下ひっくり
    かえる）


  YSRESULT MakeSingleBitBitmap(
      YsSystemFontTextBitmap &bmp,
      const wchar_t wStr[],YSBOOL reverse) const;
    UNICODE文字列wStrを表すビットマップを生成してbmpにビットマップを返す。
    1ビットが1ピクセルに対応する。

    reverseにYSFALSEを指定すると、メモリブロックの先頭がビットマップの上端
    に対応する。

    glBitmapで使うビットマップを生成するには、reverseにYSTRUEを指定する。


  YSRESULT MakeRGBABitmap(
      YsSystemFontTextBitmap &bmp,
      const wchar_t wStr[],
      const unsigned char fgCol[3],
      const unsigned char bgCol[3],
      YSBOOL reverse) const;
    UNICODE文字列wStrを表すビットマップを生成してbmpにビットマップを返す。
    fgCol, bgColは、3バイトの24ビットカラー。

    reverseにYSFALSEを指定すると、メモリブロックの先頭がビットマップの上端
    に対応する。

    glDrawPixelsでビットマップを表示するときは、メモリブロックの先頭が最下
    端に対応するので、reverseにYSTRUEを指定する。（そうでないと上下ひっくり
    かえる）


  YSRESULT MakeGrayScaleAndAlphaBitmap(
      YsSystemFontTextBitmap &bmp,
      const wchar_t wStr[],
      unsigned char fgCol,unsigned char bgCol,YSBOOL reverse) const;

    UNICODE文字列wStrを表すビットマップを生成してbmpにビットマップを返す。

    reverseにYSFALSEを指定すると、メモリブロックの先頭がビットマップの上端
    に対応する。

    glDrawPixelsでビットマップを表示するときは、メモリブロックの先頭が最下
    端に対応するので、reverseにYSTRUEを指定する。（そうでないと上下ひっくり
    かえる）
