今回は、CoreGraphics APIに頼らないテキスト描画を試してみます。処理が複雑になりがちなMLTE(Multilingual Text Engine)やATS(Apple Type Services)のAPIを使うのではなく、割と簡単な操作でテキスト描画を実現できるAPIを探してみます。
まずは話の流れとして、MLTE(Multilingual Text Engine)の方を調べてみることにします。Carbon Frameworkの一部であるでMLTEは、ある程度複雑なテキスト処理を実現したい時に用いられ、アプリケーション内に小規模のテキストエディタを実装することも可能です。関連するAPIや定数が定義されているヘッダファイルは、MacTextEditor.hでして、旧TextEdit APIのTETextBox()に相当するAPIなども準備されています。例えば、矩形領域にUnicode文字列やCFString文字列(CFStringRefで参照)を表示するAPIは以下の2つです。

TXNDrawUnicodeTextBox()はUnicode文字列の描画を行い、TXNDrawCFStringTextBox()ではCFString文字列の描画を行います。引数のiOptionsで参照するTXNTextBoxOptionsData構造体は、以下のように定義されています。

このTXNTextBoxOptionsData構造体を設定すれば、かなり複雑なテキスト描画にも対応していることが分かります。しかし両者の引数を見ると、描画用矩形領域の指示にはRect構造体が利用されており、描画座標系もQuickDraw環境のままです。これらの点から推測しても、完全にモダンなAPIとは言い難いようです(笑)。また、フォント情報等を指定するための引数であるiStyleにはATSUStyleオブジェクトを渡す必要があり、こちらについてはATS(Apple Type Services)の方のヘッダファイル(ATSUnicodeTypes.h)の定義を色々と参照する必要があります。
また、ATSUStyleオブジェクトを作成するのには、ATS APIであるATSUCreateStyle()(ヘッダファイルはATSUnicodeObjects.h)などを利用する必要があり、面倒な手続きをふまないと最終的なテキスト描画まで到達しません。APIとしては高機能なのですが、ウィンドウにちょっとしたテキストを描画したい目的には、少々複雑すぎる気がします。
まあ、フォントの種類やサイズにあまり頓着しないような簡単なテキスト描画であれば、ウィンドウの描画位置にあらかじめStatic Textコントロールを貼り付けておき、そこに以前に紹介したsetUnicodeControl()などのルーチンで、Unicode文字列を描画してやることも可能です。

多くのケースはこれで事足りるかもしれませんが、さすがにこれだけでは機能が貧弱で汎用的には使えません。そこで、文字の回転などは必要ありませんから、もう少し簡単で便利なテキスト描画用APIはないものかと探してみると、ヘッダファイルのAppearance.hの中に目的のAPIを発見しました。それが、以下のDrawThemeTextBox()です。つまり「コントロール描画でテキスト描画を担当している汎用APIを直接使う」というアイデアです。

DrawThemeTextBox()は、ウィンドウなどのカレントポート(Current Port)にテキストを描画します。このAPIも矩形領域指定にRect構造体を使いますので、やはりQuickDraw環境を引きずっている事は間違いありません。ただし、前記のTXNDrawCFStringTextBox()とは異なり、最後の引数でCoreGraphics環境のCGContextRefを指定することが可能ですので、CoreGraphicsの描画設定もそのまま引き継ぐことが可能です。つまり、描画する文字のカラーや形状等をCoreGraphics APIで指定できるわけです。
また、フォントIDにkThemeCurrentPortFontを指定すると、カレントポートのフォント設定でテキスト描画をします。つまり、描画する直前に行ったSetPortTextFont()などによるフォント設定が生きるわけです。QuickDrawのTextFont()、TextSize()、TextFace()などがすべてDEPRECATED指定で全滅したのにも関わらず、似たようなSetPortTextFont()、SetPortTextSize()、SetPortTextFace()が生き残っているのは、このAPIの存在が大きいのかもしれません(笑)。面白い機能としては、引数のinStateで、コントロール標準の描画モード(アクティブ、インアクティブ等)を複数の種類から選択可能です。

例えば、描画文字列(CFStringRef)をcref、カレントポート(CGrafPort)をport、描画対象を(CGContextRef)ctxとして、(0,0,100,20)の矩形領域に12ポイント、角ゴ W3、ノーマル、中心合わせ、赤色でテキストを描画する場合は、以下の記述となります。

筆者も、最近までテキスト描画用としてこのAPIを便利に使っていたのですが、自作アプリケーションをMac OS X 10.5(Leoperd)へ対応させる作業(さらなるモダン化)で幾つかの問題点に遭遇しました。次回はそのお話をしたいと思います。