タイトル小池邦人のプログラミング日記》2001/9/7<Quartz 2D(Core Graphics)を使う その5>カテゴリーグラフィックス, 小池邦人のプログラミング日記
作成日2001/9/7 17:0:52作成者新居雅行
今回は、Quartz 2Dで描画した図形をPDF(Portable Document Format)ファイルへと書き出し(保存)てみます。また、それを読み込んでウィンドウへ描画することにもチャレンジします。

以前に少し説明しましたが、Quartz 2DのContex(描画環境)としては、ウィンドウやBitmapだけでなく、PDFファイルを選択することもできます。この仕組みを利用することで、ウィンドウに図形を描画しているルーチンをそのまま利用し、その結果とまったく同じ状態のPDFファイルを作成することが可能です。PDFファイルの描画環境は、解像度に依存せず複数ページに出力可能な点が、他の環境とは異なります。つまり複数ページのPDFドキュメントが作成できるわけです。Quartz関連のドキュメントには、「Quartz 2Dが書き出すPDFファイルはPDF Reference Version 1.3に準拠している」と記載されていますが、現状のバージョンでは、そのすべての仕様は満たされていないようです。例えば、円の描画の実験の時に試したTacnsparency(透過処理)の設定も、PDFファイルに書き出した時点で省略されてしまうようです。

以下が、パス名(CFStringRef)で指定したPDFファイルを、Contexとして設定するcreatePDFContext()ルーチンです。

 

引数に、PDFファイルの矩形枠(用紙サイズ)とファイルへのパス名を与えると、作成されたContexを返します。まずは、パス名をCoreFoundation APIであるCFURLCreateWithFileSystemPath()に渡し、目的ファイルのCFURLRefを得ます。このように、Quartz 2D APIには、CoreFoundation APIと密接に結びついている物がいくつかありますので、CodeWarrior7.0EAのプロジェクトウィンドウのFrameworksタグに、「CoreFoundation」を追加しておくことを忘れないでください。得られたCFURLRefをCGDataConsumerCreateWithURL()に渡すと、CGDataConsumerRefを得ることができます。CGDataConsumerRefとは、前回説明したCGDataProviderRefと反対の概念であり、画像データの供給先を定義したことになります。そして、そのCGDataConsumerRefと矩形枠をCGPDFContextCreate()に渡せば、目的のContexを得ることが出来ます。必要なくなったCGDataConsumerとRefCFURLRefは、それぞれ、CGDataConsumerRelease()とCFRelease()で削除しておくことを忘れないでください。

これで、PDFファイルをターゲットとした図形描画が可能になりました。さっそく、以下のcreatePDFDocument()ルーチンで図形描画を行い、結果をPDFファイルに書き出してみます。

 

まず、あらかじめ確保したCGPointの配列に、適当な座標値(浮動小数点)を4つ代入しておきます。PDFファイルの矩形枠は、オープンしたウィンドウのサイズとします。先ほど説明したcreatePDFContext()を実行し、引数で渡されたパス名のPDFファイルをContextと指定します。後は、CGContextBeginPage()とCGContextEndPage()の間で図形描画を実行すれば、その結果がPDFファイルの1ページ目として出力され仕組みです。今回は、フレーム付き半径60ピクセルの円を4つ描き、その中心を通過する折れ曲がったラインも重ねて描画しています。

全体の処理の流れは、QuickDrawのOpenPicture()とClosePicture()の関係に良く似ていますが、データの書き出し先がファイルである点と、ページの概念がある点が異なります。具体的に描画結果をPDFファイルとして書き出すには、メニューなどが選択された時点で、以下のようにcreatePDFDocument()ルーチンを呼び出します。

createPDFDocument( window,CFSTR( "Users/koike/test.pdf" ) );

CFSTR()は、C文字列をUnicode文字列(CFStringRef)に変換するマクロです。この場合のパスは、koikeフォルダ(Mac OS Xのホームに相当)に含まれる「test.pdf」ファイルを指しています。

 

保存されたPDFファイルを、Mac OS 9環境へコピーしてきて、Adobe Acrobat Reade 5.0でオープンした様子です。

 

描画時のカラー指定では、Tacnsparencyを0.5(半透明)と指示したのですが、それがPDFファイルへ反映されていないことが分かります。

次は、先ほど保存したPDFファイルを読み込み、それをウィンドウに表示する処理を実行してみます。以前、マウスボタンをクリックしている間、ウィンドウ上に半透明の赤色の円を描き続けるpaintImageWindowX()と言うルーチンを作成しました。それを、ボタンを離した瞬間に、指定されたPDFファイルを描画するように改造してみます。

 

getWContext()はウィンドウを作成時に確保したContextを、プライベート構造体から得る自作ルーチンです。最後に実行されている...

drawPDFDocument( cont,CFSTR("Users/koike/test.pdf") );

により、test.pdfファイルの1ページ目がウィンドウに描画されます。

drawPDFDocument()は、引数で渡されたパス名からターゲットとなるPDFファイルのCFURLRefを作り、それをCGPDFDocumentCreateWithURL()に渡して描画対象となるCGPDFDocumentRefを得ています。CGPDFDocumentGetMediaBox()は、そのドキュメントの矩形枠を得るAPIです。最後に、CGContextDrawPDFDocument()に、確保しておいたContext、CGPDFDocumentRef、CGRectを渡せば、ウィンドウ上にそのPDFファイルの内容が描画されます。CGContextDrawPDFDocument()の最後の引数では、表示するページ数を指示します。マウスドラッグにより描画された円を消去することなく、新たにPDFファイルの内容が上書きされていることが分かります。

 

次回は、Quartz 2Dの描画能力をもう少し深く調査してみることにします。カラースペック、ラインの形状、パスの意味、ベジュ曲線などの詳細を見てみます。
[小池邦人/オッティモ]
関連リンクオッティモ