文字フォントのビットマップの取得方法

解決


ぴょぴょ  2007-10-18 02:28:28  No: 66594

環境:VC++2003、Win32 API(SDK)

伝言掲示板を作っています。
そこで質問します。

文字フォントのビットマップはどうやって取得すればいいの?
ビットマップが取得できないとドット単位での伝言板の表示が出来ません。
GetObject で HFONT 情報は LOGFONT 構造体より分かります。
でもこの情報だけではフォント名などしか分かりません。

一度メモリデバイスコンテキストに描画してピクセル単位で取得すれば出来ますが、
もっと良い方法はないでしょうか?ピクセル単位で取得すると低速ですので。

良い方法を知っている方は教えて下さい。
お願い致します。


YuO  2007-10-18 07:35:42  No: 66595

TrueType/OpenTypeなどのフォントはビットマップを持っていません。
持っているのは曲線情報のはずです。
# 小さいフォントを描画するために持っている物もあるが。

MSDN読む限りだと,GetGlyphOutlineでグリフの情報を取得できそうです。
が,その後の曲線を数式に沿って展開したりしないといけないことを考えると,メモリに描画するのが賢いと思います。
そもそも,フォントは「文字列」を描画することを考えて作られているので,
一つの文字のグリフを得たからといって,TextOutやDrawTextで描画したら全然違うグリフで出力される可能性もあります。


m  2007-10-18 07:47:23  No: 66596

GetGlyphOutlineは引数にGGO_GRAY8_BITMAPなどを指定すればアンチエイリアス付きのビットマップが取得できます。が、初心者には難しいかも。


ぴょぴょ  2007-10-18 08:27:39  No: 66597

YuO さん。
m さん。
ありがとう。

GetGlyphOutline を元に検索してみた。
アンチエイリアシングのことばかり書かれている。

GetGlyphOutline 関数は曲線の情報を取得するのですか?
次のリンクを読みました。
http://kone.vis.ne.jp/diary/diaryb08.html#031205
ここに文字のアウトライン取得で GetGlyphOutline が使われていて
線分とベジェ曲線を取得できるんですよね。

そのほかにビットマップも取得できるんですよね?
http://www.greenwood.co.jp/~k-aki/article/ggo_trap/index.html
でもアンチエイリアシングの5、17、65階調つきですね。
GGO_GRAY8_BITMAPで取得すると65階調でビットマップを取得して
64の値だけを使えばアンチエイリアシングがない文字のビットマップを
取得できますか?

YuO さんへ。
>一つの文字のグリフを得たからといって,TextOutやDrawTextで描画したら全然違うグリフで出力される可能性もあります。
1文字のグリフを取得して描画すると全然違うグリフになるのですか?

文字のビットマップ描画はTextOut、DrawText を使わずに描画するつもりです。
ビットマップの1ドットを4ドット(+隙間を1ドット)で描画して1文字ずつを
ちょっと大き目の文字を伝言掲示板のメッセージ表示にするつもりです。

>メモリに描画するのが賢いと思います。
メモリに描画してビットマップを取得した方が良いのでしょうか?
また見てくれたらアドバイスなどをお願い致します。


気になる…  2007-10-18 08:47:07  No: 66598

まず「伝言掲示板」にその処理が必要なのか…
そもそも「伝言掲示板」とは何なのか?


ぴょぴょ  2007-10-18 08:50:22  No: 66599

MSDN のマニュアル読んだら GGO_BITMAP 定数で
>グリフビットマップを取得します。
>メモリ割り当てに関する情報は、「解説」の項を参照してください。
となっている。
GGO_GRAY8_BITMAP よりも GGO_BITMAP 定数の方が上手く取得できますか?

DWORD dwImage[ 16 ];  // サイズはどれぐらいがいいの?
GLYPHMETRICS gm;
MAT2 mat2;

GetGlyphOutline( hDC, 取得文字コード(シフトJIS), GGO_BITMAP, &gm, sizeof(dwImage), (LPVOID)dwImage, &mat2 );

あと一番最後の引数である変換行列構造体は何ですか?
使い方は上のような引数並びであっていますか?
(引数が多いので使い方が良く分からん)


ぴょぴょ  2007-10-18 08:52:47  No: 66600

>まず「伝言掲示板」にその処理が必要なのか…
>そもそも「伝言掲示板」とは何なのか?
むかし街角であった4色の電光掲示板です。
あっ。言葉を間違っていた。

電光掲示板でした。


ぴょぴょ  2007-10-19 05:10:20  No: 66601

ぴょぴょです。

GetGlyphOutline と GGO_BITMAP でいろいろとネット検索した結果です。
(1) その35 高速フォント表示(アンチエイリアス無しバージョン)
    http://marupeke296.com/DXG_No35_FontNoAntialiasing.html
(2) GetGlyphOutline関数のフォント位置
    http://marupeke296.com/WINT_GetGlyphOutline.html
この2つのリンクを発見しました。
ほかにもたくさん見つかった。

>あと一番最後の引数である変換行列構造体は何ですか?
いろいろと検索したら MAT2 とは 2×2 の行列のようです。
それから MAT2 構造体の中に FIXED 構造体がありました。
FIXED 構造体は整数部、小数部の情報で拡大、縮小、回転行列を入れるそうです。
簡単にまとめてみました。
------------------------------
// 構造体
typedef struct _MAT2 {
  FIXED eM11;  // 2×2行列の(1,1)
  FIXED eM12;  // 2×2行列の(1,2)
  FIXED eM21;  // 2×2行列の(2,1)
  FIXED eM22;  // 2×2行列の(2,2)
} MAT2, FAR *LPMAT2;

// 構造体
typedef struct _FIXED {
  WORD  fract;  // 小数部(符号なし)
  short value;  // 整数部(符号付き)
} FIXED;

小数部は65536(=2^16)を分母にしたときの値を持っている。
普通の小数に直すには value + fract / 65536 と計算する。

MAT2には拡縮・回転行列を入れる
等倍{ 0, 1 }{ 0, 0 }{ 0, 0 }{ 0, 1 }
回転{ cos }{ -sin }{ sin }{ cos } doubleを65536倍してFIXEDにする。

MAT2 mat2 = { {0,+1}, {0,0}, {0,0}, {0,+1} };  // 回転なし
MAT2 mat2 = { {0,-1}, {0,0}, {0,0}, {0,+1} };  // 左右反転
MAT2 mat2 = { {0,+1}, {0,0}, {0,0}, {0,-1} };  // 上下反転
MAT2 mat2 = { {0,-1}, {0,0}, {0,0}, {0,-1} };  // 180°回転
------------------------------
ソースは次のようになりました。

MAT2 mat2 = { {0,1}, {0,0}, {0,0}, {0,1} };  // 回転なし
GLYPHMETRICS gm;
DWORD  dwSize;
LPBYTE lpByte;

// サイズの取得
dwSize = GetGlyphOutline( hDC, 'A', GGO_BITMAP, &gm, 0, NULL, &mat2 );
// 動的確保
lpByte = (LPBYTE)GlobalAlloc( GPTR, dwSize );
dwSize = GetGlyphOutline( hDC, 'A', GGO_BITMAP, &gm, dwSize, (LPVOID)lpByte, &mat2 );
// 次のリンクを参考にビットマップを取り出す
http://marupeke296.com/DXG_No35_FontNoAntialiasing.html
// 描画位置
dx = x +               gm.gmptGlyphOrigin.x;
dy = y + tm.tmAscent - gm.gmptGlyphOrigin.y;
------------------------------
この質問は解決しました。

GetGlyphOutline 関数名を教えてくれた YuO さん、
GGO_GRAY8_BITMAP 定数を教えてくれた m さん。
有り難うございました。
解決。


ぴょぴょ  2007-10-19 05:11:01  No: 66602

解決チェックし忘れた。
ごめん。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加