« CharPrevWとCharNextW | トップページ | GetTextExtentExPoint »

2007年1月 6日 (土)

Tab文字の展開

文字列にTab文字(U+0009)が含まれている時、何も考えずに、Windows32APIのTextOutやExtTextOutで文字列を描画すると、通常は、Tab文字は使用するフォントのDefaultCharのグリフに置き換えられて描画されてしまう。下のイメージのように。

Exttextouttahoma

DefaultCharというのは、使用するフォントに対応するグリフが無いときに使用される文字である。ちなみに、DefaultCharは、GetTextMetricsで取得できる構造体のtmDefaultCharメンバで取得できる。上の図はフォントにTahoma(DefaultCharはU+001F)、下の図は、MSゴシックを使用したきの図である(DefaultCharはU+FF65)。

Exttextoutgothic

ところで、よくテキストエディタではTab文字を使用して位置揃えを行えるようになっている。そこで、便利なAPIがWindowsに用意されている。TabbedTextOutとGetTabbedTextExtentである。下にこれらのAPIを使って文字列を描画したときのイメージを示す。

Tabbedtextout

どれも、「ABC + Tab文字 + DEFG + Tab文字 + あいうえ」という文字列をTabbedTextOutに渡すパラメータを変えながら、描画したときのイメージである。上から順に、第2引数の描画開始位置のX座標を、それぞれ30、20、0にして渡している。よく、テキストエディタでTab文字を含むテキストを表示したときのイメージと同じように、表示されているのがわかる。ここで、ポイントは、第8引数のnTabOriginである、ここにタブの展開を開始するX座標を指定するのであるが、どの場合も0を指定している。よって、たとえ、第2引数の文字列の描画開始位置のX座標を30、20、0と変えてもタブ展開の開始位置を揃えているので、上のイメージのように、Tab文字の次の文字の位置が揃うのである。このように便利な機能を提供してくれるが、一つ困ったことがある。それは文字列の幅の取得である。

GetTabbedTextExtentで、一見するとTab文字を展開した後の文字列の幅が取得できるのであるが、この引数を見ると、足りないものが一つある。それは、nTabOriginがないのである。すなわち、このAPIはnTabOriginを0とした時の幅しか返さないのである。

上のイメージを見てもわかるように、TabbedTextOutのnTabOriginに渡すパラメータと描画開始位置によって文字列の幅(イメージの先頭文字の「A」の左側から最後の文字「え」の右側まで)が変わるのだ。ちょっと、ありゃありゃと思っていたら、取得する方法があった。それは、なんと

TabbedTextOutの戻り値の下位ワードに幅が返されるのだ。

これを知って喜んだのだが、すぐに、気づいたのが、TabbedTextOutを呼び出すってことは、実際に文字列をデバイスコンテキストに描画しなければならないってことだ。はぁ。

色々書いたが、まぁ、TabbedTextOutを呼び出して幅を求めるのは、Tab文字を展開しないときに使用するGetTextExtentPoint32と比較してそこまでパフォーマンス悪いとは言えないのかもしれない。GetTextExtentPoint32で幅を求めるときも、どの道、GDIのレンダリングエンジンに文字列を渡し、描画イメージを求めなければ、求められないのだから(たぶん)・・・TabbedTextOutで幅だけを求める場合、クリッピング領域外に描画させて求めればとりあえずは問題ないのかもしれない。

補足して、実際はTabbedTextOutWやGetTabbedTextExtentWなどのUnicode版を使用したのが、ANSI版とUnicode版の表記を使い分けるのは面倒なので、ことわりが無い限りUnicode版を指す。それと、Windowsで使用するフォントにグリフが無いときに、そのフォントのDefaultCharのグリフが使われると書いたが、どうも、見てると、複数のグリフが使われてるっぽい。たぶん、これは、フォントリンクの影響だと思う。Windowsでは、フォントのリンクが設定されていれば、たとえ、使用するフォントにグリフがなくても、リンクされたフォントのグリフを探しにいく。で、ここでもグリフがみつからないと、このフォントのDefaultCharのグリフが使われてるのでは?と。

« CharPrevWとCharNextW | トップページ | GetTextExtentExPoint »

Windows」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/1497665/39651906

この記事へのトラックバック一覧です: Tab文字の展開:

« CharPrevWとCharNextW | トップページ | GetTextExtentExPoint »

自作ソフトウェア

無料ブログはココログ

メモ