タイトル小池邦人のプログラミング日記》2001/8/25<Quartz 2D(Core Graphics)を使う その3>カテゴリーグラフィックス, 小池邦人のプログラミング日記
作成日2001/8/27 10:20:46作成者新居雅行
今回は、自作CarbonアプリケーションでQuartz 2Dを利用し、実際に何か図形を描画してみることにします。

AppleサイトにはMac OS 9.2.1 Updaterが登録され、そのシステムには、しっかりとCarebonLib 1.4が含まれています。これで、Classic環境側は準備万端となりました。後は、9月にMac OS X 10.1が発表されるのを待つだけです。Appleのドキュメントサイトも5月以来、久しぶりに更新されました。お馴染みの「Carbon Porting Guide」や「Handling Carbon Events」といったドキュメントは、若干内容が変更されているようです。その中でも、以下のサイトに登録されている「Setting Up MLTE to Use Carbon Events」というドキュメントは、まったくの新規内容となっています。「Multilingual Text Engine(MLTE)」を利用されている方は、一読しておいた方が良いでしょう。

◇Setting Up MLTE to Use Carbon Events
 http://developer.apple.com/techpubs/macosx/Carbon/text/MultilingualTextEngine/multilingualtextengine.html

さて、この最新&更新ドキュメントのリストに、以前に紹介した「Drawing With Quartz 2D」(drawingwquartz2d.pdf)が上がっていました。喜んでダウンロードしてみたのですが、何故だか内容は前とまったく同じです(涙)。どうも、Carbonドキュメントのリストに「Quartz 2D」が追加されたので、ここにも載っただけのようです。がっかりしてしまいました。

さて、Quartz 2Dの図形描画能力ですが、これは「PostScript」を勉強した事がある人なら、ほぼ、それと同等だと考えてください。Mac OS Xの前身であるNEXTSTEPには、描画エンジンとして「Display PostScript」が使われていたのは有名な話しです。PostScript自体は、フォース(Forth...憶えている人はいるだろうか?)に似たイメージング言語なのですが、Quartz 2Dには、そうした言語仕様は存在していません。Quartz 2Dの図形描画能力を調査していると、昔々、Macintosh用の「LaserTalk」というアプリケーションでPostScriptをプログラミングし、直接LaserWriter(プリンター)に送って出力結果を確認していたのを思い出してしまいました(笑)。PostScriptについては、以下のAdobeのサイトに「The PostScript Language Reference Manual」というリファレンスがありますので参照してみてください。バージョンが最新かどうかは未確認ですが、これについては日本語訳も出版されていると思います。

◇The PostScript Language Reference Manual
 http://partners.adobe.com/asn/developer/technotes/postscript.html

Quartz 2Dを語るとき、もうひとつ忘れてはいけないのは(忘れられてしまっているだろうが...)「QuickDraw GX」との関係です。もともと、Macintoshに搭載されていたQuickDrawは、文字表示やベクトル系の図形描画が弱かったため、それらを補うためにQuickDraw GXが開発されました。「Quickraw 3D」や「OpenDoc」よりも、もっと昔の話しです(笑)。ただ、メモリー食いで、すべてのシステム(旧Mac OS)に標準で実装されるのが遅れたため、サードパーティが利用するのをためらい、そうしている間に消えていってしまいました。ただ、その開発成果(遺伝子)は、ベクトルグラフィックスについては「QuickTime」に、文字描画については「ATUI」や「MLTE」に引き継がれています(多分)。よって、Quartz 2Dには、このQuickDraw GXの開発成果がいくらか利用されているのではないかと推測しています(きっと)。

さっそくQuartz 2Dを利用し、図形を描画してみることにします。まず、最初から訂正です。前回紹介したcreateWindowContxt()ルーチンは、間違ったソースコードを添付してしまいました。申し訳ないです。今回紹介する方が正しいですので、利用されている方は差し替えておいてください。

 

まず、アプリ側でウィンドウを作成したら、createWindowContxt()を利用し、そのウィンドウのCGrafPortを、Quartz 2DのContextとして設定します。このアプリは、確保したCGContextRefを、ウィンドウ個別に用意されているWCore構造体に保存しておきます。また、ウィンドウを閉じる時には、保存しているCGContextRefをQCGContextRelease()に渡し、作業領域を開放することも忘れないでください。WaitNextEvent()やCarbon Eventでマウスクリックが発生したら、その座標値を、GlobalToLocal()でウィンドウのローカル座標に変換してから、paintImageWindowX()に渡します。

paintImageWindowX()の最初に実行しているgetWContext()は、ウィンドウのWCore構造体から、保存されているCGContextRefを抽出する自作ルーチンです。続いて、CGContextSetRGBFillColor()で、図形の描画カラーを決定します。Quartz 2Dでは、APIのほとんどの引数が浮動小数点を受け取ります。ちなみにRGB値の場合は、各1.0が256階調で言うところの255値に相当します。今回のテストでは、赤色を設定していることが分かります。QuickDrawとは異なり、このAPIの最後の引数にはトランスペアレンシー(透明度)を設定することができます。ここでは試しに0.5を代入し、半透明な赤色で描画されるようにしてみます。

次のCGContextBeginPath()で、新規「Path」を作成することをQuartz 2Dに指示します。Pathについての詳しい解説は次の機会にするとして、とりあえずQuickDrawのOpenPicture()やOpenPoly()と似たようなAPIだと考えてください。続いて、CGContextAddArc()で円弧をPathに追加します。カラー値と同じく、Quartz 2D APIに座標やサイズを渡すのには浮動小数点を使います。ディフォルトでは1.0が1/72インチ(1ポイント)となっています。1.0が、QuickDrawで指示する1ピクセルに相当するわけです。この比率は、前回説明したCurrent Transformation Matrizx(CTM)を再設定することで、簡単に変更することができます。

CGContextAddArc()の最初の引数は、描画対象のCGContextRefです。次の2つが円弧の中心座標、次が半径、そして、回転開始角度(radian)と終了角度、最後は回転方向となります。今回は、このAPIを利用してウィンドウ上に半径30ピクセルの円を描画してみます。Pathに円弧の追加が終了したら、CGContextFillPath()を呼び出して、先ほど設定した色でPathの中身を塗ります。これによりマウスドラッグしている間、その位置に半径30ピクセルの半透明赤色の円が描画され続けます。ただし、この時点ではウィンドウサーバのバッファに描画されただけですので、実際のスクリーン上に表示するためには、CGContextFlush()を実行します。透明度を0.5にしたことにより、描画結果の所々に赤色の濃淡ができていることが分かります。

 

続いて、マウスドラッグに円描画が追随し、マウスを離した時点でその位置に固定されるように、上記のソースコードを変更してみます。

 

直前の座標位置を白色の円で消去してから、新しい座標値に赤色の円を再描画します。注意する点は、赤色で描画された円はアンチエイリアス処理(Quartz 2Dの特徴)されており、エッジが若干大きくなっていることです。よって、きっちり30ピクセルの円で消去しようとすると、円の回りに少しゴミが残ってしまいます。そこで、消去側の円の半径は31ピクセルと、少し大き目に設定しておきます。

 

CGContextFlush()は、赤色の円を描いたタイミングで1度だけ呼び出します。これにより、円を消去する時の「スクリーン上のちらつき」を防ぐ事が出来ます。つまり、Mac OS 9でオフスクリーンバッファのテクニックを用いていたのと同じ効果を得られるわけです。同じ理由で、一度描画した内容はウィンドウサーバのバッファ上にあるので、ウィンドウを移動したり、別のウィンドウで隠して再度切り替えるといった操作でも、消されることはありません。試してみてください。

次回は、今回説明することができなかった、QuickDrawのイメージ(PixMap画像)をQuartz 2Dで描画することにチャレンジしてみます。
[小池邦人/オッティモ]
関連リンクオッティモ