この回答は、マイクロソフトの秘密の文書を巡って試行錯誤してまとめたものです。それはExtTextOutとのDrawText間の選択である(と反射に、私はそれが望ましいと思います)カーニングが必要な場合は
* TextOut, which does not kern
* ExtTextOut, which can kern if its final parameter is non-null
* DrawText, which always kerns
:
MSDN Cライブラリのテキストを表示するには、以下の機能を提供します。
DrawTextは、Grooによって提案された行に沿った解決策を提供します。それはのように、テキストエリアの周りに描画する ボックスを必要とします。
void textOut(HDC hdc, int x, int y, char *s, int l)
{
RECT r = {0};
r.left = x;
r.right = Ewidth;
r.top = y;
r.bottom = y+LineHt;
DrawText(hdc,s,l,&r,DT_NOPREFIX);
}
フォントサイズを設定または変更されている場合は、文字幅ルックアップテーブル「CharW」に構築する必要があります。
ABC CharW[256]; // char-width including leading/trailing space
GetCharABCWidths(hdc, 0, 0xff, CharW);
フォントが変更され、カーニングテーブルを構築する必要がある場合:
KERNINGPAIR *Kern; // pairs of chars and the (usually negative) additional gap between them
int KernCnt; // number of same
KERNINGPAIR *CharK[256];// ptr to first kerning-pair for each char
if(!Kern)
free(Kern);
KernCnt = GetKerningPairs(hdc, -1, 0);
Kern = malloc(KernCnt * sizeof(*Kern));
GetKerningPairs(hdc, KernCnt, Kern);
{
int i;
for(i = 0; i < KernCnt; ++i) {
KERNINGPAIR *k = Kern+i;
if(k->wFirst < 0x100) {
KERNINGPAIR **k2 = CharK + k->wFirst;
if(!*k2)
*k2 = k;
}
}
}
安全な再生するには、カーニングテーブル「カーン」は(wFirst、wSecond)によってソートされなければならないが、ように見えますクラスタ私のコードはqsortなしで動作します。
次のように我々は、従って、任意のサブ画素幅を算出することができる:
int pixelWidth(char *s, int l)
{
int x = 0;
int i;
for(i = 0; i < l; ++i) {
char c = s[i];
ABC *w = CharW+c;
int wk = 0;
if(i > 0) {
char b = s[i-1];
KERNINGPAIR *k = CharK[b];
if(k)
for(; k < Kern+KernCnt && k->wFirst == b; ++k)
if(k->wSecond == c)
{wk = k->iKernAmount; break;}
}
x += wk + w->abcA + (w->abcB) + w->abcC;
}
return x;
}
これはテストされ、x座標フラグが設定されている保持電流が座標ときのDrawTextによって返されると一致しています。
SetTextAlign(hdc,TA_UPDATECP)
したがって、指定されたピクセル幅に一致する部分文字列長を見つけることは簡単です。しかし、簡単な解決策は、ExtTextOutによって提供される
:
INT W[512]; // maximum string-length
void textOut(HDC hdc, int x, int y, char *s, int l)
{
GCP_RESULTS g={0};
g.lStructSize = sizeof(g);
g.lpDx = W;
g.nGlyphs = sizeof(W)/sizeof(*W);
GetCharacterPlacement(hdc, s, l, sizeof(W), &g, GCP_USEKERNING);
ExtTextOut(hdc, x, y, 0, 0, s, l, g.lpDx);
}
MSDN関数てGetCharacterPlacement()は、文字列s内の各文字の実際のピクセル幅を有する配列を返します。上記の私のルックアップテーブルCharW、Kern、CharKを置き換えます。マイクロソフトによれば、Uniscribe機能に取って代わられているが、英語のようなヨーロッパ言語でもうまく機能する。
「Visual C」とは何ですか、なぜタグがないのですか?とにかく、それは言語の問題ではありません。 – Olaf
どのようにテキストをレンダリングするかによって異なりますが、基本的な考え方です。カーニングがない場合は、文字幅ごとにルックアップテーブルを作成し、オフセットを簡単に計算できます。あなたのレンダリング関数がカーニングを使用している場合、または空白を追加してテキストを正当化する場合は、それを測定する適切なマッチング関数を使用する必要があります。メモ帳は通常、固定幅のフォントを使用していますが、可変長フォントのカーニングは何の疑いもありません。 – Groo
ありがとうGroo - 私は考えを得る。 TextOut(少なくともデフォルトでは)はカーン化していないようですので、私の仕事は比較的簡単です。 GetCharWidth32()を使用してルックアップテーブルを生成することができます(確認する)。 メモ帳に関しては、奇妙なことに、それはカーネルに表示されます(または私のWin7版ではそうです)。 Times New Romanでは、「AV」は、フォントサイズ12で1ピクセル、フォントサイズ18で2ピクセル、24インチで3などの中間オーバーラップを示します。オフセットを測定するためにどのような機能が使用されているのか、それともカーニングがどのように機能するのかはわかりませんが、私のプログラムではカーニングなしで行うことができます。 –