● 新ToolBox100の定石(2000/12/12)

〜 プリントアウトはニューフェースで 〜


今回は、画像のプリントアウトについて解説したいと思います。プリントアウトには、Carbon環境から新しく導入された「Carbon Print Manager」を使うことになります。

Carbon環境には、APIが完全に書き換えられている二つのToolBox Managerが存在します。そのうちの一つがPrint Managerです(もう一つはScrap Manager)。Print Managerは、ToolBoxの中でも発表以来ほとんど変更されることがなかった「最古」のManagerです。よって、Apple社はMac OS Xを導入する機会に「Print Managerの大修理が必要!」と判断したようです。旧Print Managerに関連するUniversal Headerは「Printing.h」だったのですが、CarbonLibでは「PMApplication.h」を用いますので注意してください。旧APIとの区別のために、新APIの名称の先頭には必ず「PM」の文字が入っています。

ViewJPEGのプリントアウトに関わるメニュー項目は、ファイルメニューの「用紙設定...」と「プリント...」です。どちらも前回の「保存...」と同様に、clickFileMenu()でメニューアイテム番号がチェックされてから適切な処理へと分岐されます。



「用紙設定...」を担当するのがdoPageSetup()ルーチンです。doPageSetup()は、セレクターで選択されているプリントドライバの「用紙設定ダイアログ」をオープンし、ユーザが用紙情報を変更できるように準備します。



ViewJPEGでは用紙情報を保存しておくための「PMPageFormat」を、外部変数の「p_form」に確保しています。これにより、一度ダイアログでセットされた情報は、アプリケーションが終了されるまで保持されます。PMPageFormatとは用紙情報を保存する構造体を参照しているポインターだと考えてください。QuickTimeでよく利用する「Movie」と同類で、その内部構造は公開されていません。よって、保存されている情報にアクセスするのには、必ずアクセッサーAPIを利用します。

Carbon Print Managerを使う処理は、必ずPMBegin()で開始しPMEnd()で終了する必要があります。続いて、p_formが未定義(ゼロ)の時だけgetDefaultPageFormat()でディフォルトのPMPageFormatを保存します。それ以外の場合には、すでに確保さているp_formをそのまま利用します。PMPageSetupDialog()にp_formを渡すと、用紙情報を表示したダイアログがオープンされ、返ってきたchkの値がTRUEならば、ユーザがダイアログの「OK」ボタンを押したことになります。

現在のViewJPEGでは、アプリケーションが保管している用紙情報を、どのドキュメントも共通で使うことになります。しかし、ドキュメントごとに用紙情報を保持しようとすると、処理はもう少し複雑になります。doPageSetup()にドキュメントウィンドウのWindowPtr(現在は利用していない)を渡しているのも、将来的にはドキュメント個々に用紙情報を持たせるための準備です。通常こうしたドキュメント固有の用紙情報は、そのファイル付加されている'PREC'リソースに保管しておきます。



例えば、こうした仕組みを考慮した処理を旧Print Manager APIで記述すると、以下の様になります。



まずはドキュメントファイルの'PREC'リソースに保存されていた用紙情報(TPrint構造体)のハンドラ(THPrint)を抽出します。そしてそれをPrStlDialog()に渡します。通常は、読み込んだTHPrintの内容がドライバに対して適正かどうかを判断する処理も必要となります。THPrintが未定義(ゼロ)の場合にはPrintDefault()によりディフォルト状態をセットしています。これをCarbon Print Managerで記述し直すと以下の様に変わります。



Carbon Print Managerでは、TPrintの代わりにPMPageFormatを利用します。まずは、リソースから得たドキュメントの用紙情報(ハンドラ)をPMUnflattenPageFormat()に渡し、PMPageFormatに変換します。ドキュメントの用紙情報が未定義(ゼロ)の場合にはPMNewPageFormat()とPMDefaultPageFormat()を使い、新しいディフォルトPMPageFormatを作成します。ユーザがダイアログで「OK」ボタンを押せば、PMFlattenPageFormat()によりPMPageFormatから新しいハンドラを作り、それをドキュメントに保存し直すために引数へ返します。この処理ではPMPageFormat自身を保存しているわけではないので、作業が完了したらPMDisposePageFormat()で、PMPageFormatが占有していたメモリを解放します。

ところで、Mac OS Xではリソースフォークへのリソースデータの保存は推奨されていません。しかし、PICTやJPEGファイル、もしくはプレーンのTEXTファイルに用紙情報を付加するには、今まで利用してきたこの方法しかないような気もします。はてさてどうするのでしょうか?それともドキュメントもバンドル化してしまうのでしょうか(笑)。

ドキュメント(JPEG画像)のプリントアウトは、doPrintOut()ルーチンが担当です。



こちらの処理も、doPageSetup()と同様に、PMBegin()で開始しPMEnd()で終了させます。プリントアウトの場合には、PMPageFormatだけではなく、「プリントダイアログ」の設定情報を保存しておくために「PMPrintSettings」も準備します。それに関する処理は、PMNewPrintSettings()とPMDefaultPrintSettings()の両ルーチンが行います。実際にプリントダイアログをオープンするのはPMPrintDialog()の仕事です。これが返したchkの値がTRUEであれば、ユーザが「OK」ボタンを押したことになり、画像プリントアウト担当のimagePrint()ルーチンを呼び出します。そして、最後に確保したPMPrintSettingsをPMDisposePrintSettings()で削除しています。imagePrint()が最初に行う仕事は、画像データが保存されているオフスクリーンをロックし、makePrintPicture()でPICTデータを作成することです。



OpenPicture()とClosePicture()で挟まれているCopyBits()によりPICTが作成されます。CopyBits()の引数には、Carbon環境に準拠するようにGetPortBitMapForCopyBits()が利用されています。makePrintPicture()は、プリンターへのデータ転送中にメモリ不足が発生しないよう、画像を短冊状に細かく分割したPICTデータを作成しています。こうしないと、昔のMacintosh環境では、大サイズのフルカラー画像をPostScriptプリンターへ転送する時に頻繁にエラーが発生していました。しかし、最近ではアプリケーションやプリンターが使えるメモリ容量も増大し、OS側の処理も改善されていますので、代わりに以下のような単純なPICT作成ルーチンを利用しても問題ないでしょう(多分)。



さてプリント用のPICTデータが完成したら、プリント環境での描画を実現するためにPMBeginDocument()にPMPageFormatとPMPrintSettingsを渡し、代わりに「PMPrintContext」を得ます。これを、PMGetAdjustedPageRect()で得た出力用紙サイズといっしょにPMBeginPage()に渡せば、1ページをプリントアウトするための準備が整いました。PMGetGrafPtr()でプリント用のCGrafPtrを得たら、それをSetPort()でカレントポートにセットし、DrawPicture()でPICT画像を描画します。このように、実際のプリントアウトは、プリント用のポートに対してQuickDrawを用いた描画を行うことで実行されるわけです。



この仕組みは旧Print Manageから変わっていません。旧Print Managerでプリントアウト処理を実現したことがある方なら、新APIでの処理の流れを理解するのは難しくないと思います。ワープロのように複数ページにまたがったデータをプリントアウトしたい場合には、PMGetAdjustedPageRect()以下の処理を指定ページ分だけループさせればOKです。PMEndPage()とPMEndDocument()で、プリント作業で確保したメモリを解放した後に、KillPicture()でPICT画像自身も削除します。最後にオフスクリーンのロックを解除し、カレントポートを初期値に戻せば作業は完了です。

最後にCarbonLib v1.2 SDK(現在は開発途上)でCarnbon Print Managerを用いる時の注意を述べておきます。Carbon Print ManagerのAPIは、今までと同じ手法を用いてプリントを実行するグループと、セッションプリント(複数のプリントアウトを複数のプリンターに同時に行える仕組み)を用いるグループに分かれています。どうもCarbonLib v1.2のUniversal Interfaces 3.4dでは、ディフォルトでセッション用のグループが選択されているようです。よって、先んじて「#define PM_USE_SESSION_APIS 0」と定義し直したPreCompiled Headerを作成しておかないと、非セッション用のAPIがリンクできません。これは一時的な状況かもしれませんが、注意が必要なので憶えておいてください。

さて、今回で第一部は終了となります。21世紀にお届けする第二部では、ViewJPEGアプリケーションをもっと有用なアプリケーションへと改良していく過程を解説する予定です。第二部にもご期待ください!!

copyright 2000 Ottimo, Inc. All rights reserved
無断転載・引用禁止
Contact Us: koike@ottimo.co.jp