ページ 11

GetGlyphOutline関数等について

Posted: 2010年7月06日(火) 16:22
by シエル
最近質問が多くてすみません。
下記URLの高速なフォント描画について、お聞きしたことがあります。
http://www3.pf-x.net/~chopper/home2/DirectX/CDX30.html

【質問①】
このページのソースにある、ポリゴンの頂点をセットするSetPorigon関数についてです。
この関数には頂点構造体(p)、x1(左上頂点x),y1(左上頂点y),x2(テクスチャの横幅),y2(テクスチャの縦幅)を
渡して、座標をセットしているようなのですが、
左上頂点以外の頂点で-1されている部分があります。

なぜ-1しなければならないのか、理由が分からないのでご教授願います。。

void setPorigon(PTRIANGLE p,float x1,float y1,float x2,float y2)
{
p[0].x = x1;
p[0].y = y1;
p[0].z = 0.0f;
p[0].rhw = 1.0f;
p[0].color = D3DCOLOR_XRGB(255,255,255);
p[0].tu = 0.0f;
p[0].tv = 0.0f;

p[1].x = x1 + x2 - 1;
p[1].y = y1;
p[1].z = 0.0f;
p[1].rhw = 1.0f;
p[1].color = D3DCOLOR_XRGB(255,255,255);
p[1].tu = 1.0f;
p[1].tv = 0.0f;

p[2].x = x1 + x2 - 1;
p[2].y = y1 + y2 - 1;
p[2].z = 0.0f;
p[2].rhw = 1.0f;
p[2].color = D3DCOLOR_XRGB(255,255,255);
p[2].tu = 1.0f;
p[2].tv = 1.0f;

p[3].x = x1;
p[3].y = y1 + y2 - 1;
p[3].z = 0.0f;
p[3].rhw = 1.0f;
p[3].color = D3DCOLOR_XRGB(255,255,255);
p[3].tu = 0.0f;
p[3].tv = 1.0f;
}


【質問②】
二つ目はGetGlyphOutline関数によって、確保される配列についてです。
このページのソースにもありますが、下記のように実行するとpfontbitmapのアドレスに指定した文字の
ビットマップデータが格納されますが、このバイト型の配列のどのような並びでビットマップデータが
入っているのかがイメージできません。
*pfontbitmap = new BYTE[fontsize];
GetGlyphOutline(hdc,fontcode,GGO_GRAY4_BITMAP,pgm,fontsize,*pfontbitmap,&mat))

このデータをその後下記のように読み込んで、動的テクスチャにピクセルデータを書き込んでいっているのですが、先ほど確保した配列を読み込む部分だけ意味が良く分かりません。(下記赤字部分のみ)
どのようにビットマップデータが格納されているのかが分かっていれば、イメージができるようになり、
自分で考えてコードが組めるようになるのですが、このままではコピるしかありません。
どなたか、この確保した配列にどのようにビットマップデータが格納されているのかが分かる方、
具体的に説明していただけますでしょうか?
よろしくお願い致します。

一応このページの全ソースコードを添付しておきます。


//フォントの書き出しの一番左X座標
int offsetx = pgm->gmptGlyphOrigin.x;
//フォントの書き出しの一番左Y座標
int offsety = ptm->tmAscent - pgm->gmptGlyphOrigin.y;
//フォントビットマップの横幅を調べる
int bitmap_width = pgm->gmBlackBoxX + (4-(pgm->gmBlackBoxX%4)%4);
//フォントビットマップの縦幅を調べる
int bitmap_height = pgm->gmBlackBoxY;
//フォントレベル
int fontlevel = 17;
BYTE *pPixel;



//テクスチャサーフェイスを初期化する
FillMemory(rc.pBits , rc.Pitch * ptm->tmHeight, 0);

//フォントビットマップをテクスチャに書き込む
for (int y = offsety; y < offsety + bitmap_height; y++)
{
for (int x = offsetx; x < offsetx + bitmap_width; x++)
{
DWORD a = 255 * (*pfontbitmap)[x - offsetx + bitmap_width * (y - offsety)] / (fontlevel-1);
//フォントの色を決める
DWORD fontcolor = 0x00FFFFFF | (a<<24);
//現在のピクセル位置の計算
pPixel = ((BYTE*)rc.pBits) + (x * 4) + (y * rc.Pitch);
//フォントビットマップの書き込み
memcpy(pPixel, &fontcolor, sizeof(DWORD));
}
}

//テクスチャのアンロック
g_ptexture9->UnlockRect(0);

return S_OK;

Re:GetGlyphOutline関数等について

Posted: 2010年7月06日(火) 17:33
by ISLe
> 【質問①】
(略)
> なぜ-1しなければならないのか、理由が分からないのでご教授願います。。

-1する必要はないですね。
リンク先のページは一般的なピクセル座標と勘違いしていると思います。
変換済み頂点座標は画面のピクセルの中心ではなくて、ピクセルとピクセルのあいだを指しますから、例えば0
~640で640ピクセル幅になります。

テクスチャの歪み解消のためにすべての座標から-0.5fしておくと良いかもしれません。


> 【質問②】

GetGlyphOutline
http://msdn.microsoft.com/ja-jp/library/cc410385.aspx
によると
> GGO_GRAY4_BITMAP フラグが指定されているときに返されるビットマップは、位置調整がダブルワードの行方向のバイト配列で、0~16 までの値を保持します。

・1ピクセル1バイトで0~16の値を持つ
・横方向サイズは4バイト単位に切り上げられる
(↑のページには書いてないけど)上下反転している

--編集
すみません。上下反転はしてなかったです。
画像

Re:GetGlyphOutline関数等について

Posted: 2010年7月06日(火) 18:55
by シエル
ISLeさん。ありがとうございます。

>>-1する必要はないですね。
>>リンク先のページは一般的なピクセル座標と勘違いしていると思います。

テストで実行してみたのですが、マイナス1しないと、微妙に文字が一部欠けた感じになりましたので、
やっぱりマイナス1は必要なのだと思われます。

>>変換済み頂点座標は画面のピクセルの中心ではなくて、ピクセルとピクセルのあいだを指しますから、例えば
>>0~640で640ピクセル幅になります。
>>テクスチャの歪み解消のためにすべての座標から-0.5fしておくと良いかもしれません。

変換済み頂点座標はピクセルの中心ではなくて、ピクセルとピクセルの間なんですね。
これは知りませんでした。覚えておきます。


>>GGO_GRAY4_BITMAP フラグが指定されているときに返されるビットマップは、位置調整がダブルワードの行方向>>のバイト配列で、0~16 までの値を保持します。
>>・1ピクセル1バイトで0~16の値を持つ
>>・横方向サイズは4バイト単位に切り上げられる

ちょっとイメージできましたが、まだ引っかかる部分があるので後でまた書き込みます。



追記:
画像貼りました。
左が-1してないやつで、右側がー1したものです。
左側のほうが一部ギザギザしてしまってます。 画像

Re:GetGlyphOutline関数等について

Posted: 2010年7月06日(火) 21:08
by シエル
座標をマイナス1しなければならない理由はまだ分かりませんが、
↓の配列を読み込んでいる方法はよく考えたら分かって、イメージできました。
失礼しました。。。
DWORD a = 255 * (*pfontbitmap)[x - offsetx + bitmap_width * (y - offsety)] / (fontlevel-1);

Re:GetGlyphOutline関数等について

Posted: 2010年7月06日(火) 22:44
by シエル
GetGlyphOutline関数で取得される、GLYPHMETRICS構造体の値は長さではなくて、
ピクセル数を取得してるような感じなので、-1しないと合わないのかなと思いました。
msdn探しても、GLYPHMETRICS構造体のメンバの詳しい説明が載ってないので、そう割り切ります。
なので、解決にします。

ISLeさん!ありがとうございました!

Re:GetGlyphOutline関数等について

Posted: 2010年7月07日(水) 02:08
by ISLe
-1しないとギザギザになるので根拠無しに-1しているのではないでしょうか。

一方だけ-1するとサイズが短くなってしまいますよ。

このサンプルだと文字が描かれている範囲がテクスチャサイズよりずっと小さいので違いが分からないですがタイルマップで座標指定するときとかはチップマップに隙間ができます。

No:56133に書いたように歪みを解消するにはすべての座標から-0.5fすると良いです。
#マイクロソフトが推奨している方法ですし。

Re:GetGlyphOutline関数等について

Posted: 2010年7月07日(水) 02:46
by ISLe
http://marupeke296.com/WINT_GetGlyphOutline.html
↑のページの説明が分かりやすいかと。

GLYPHMETRICS Structure
http://msdn.microsoft.com/en-us/library/dd144955(VS.85).aspx
#日本語のページはありませんでした

gmCellIncYは0が返りますね。
縦書きフォントだとgmCellIncYに値が入ってくるのかな(未確認)。

Re:GetGlyphOutline関数等について

Posted: 2010年7月07日(水) 09:22
by シエル
全ての座標からマイナス0.5しても、ギザギザが無くなって綺麗に描画されました!
色々とありがとうございました!