Quartz 2D の概要
Quartz 2D は、iOS 環境およびカーネル外のすべての Mac OS X アプリケーション環境からアクセス可能な 2 次元描画エンジンです。Quartz 2D アプリケーションプログラミングインターフェイス(API) を使用すると、パスに基づいた描画、透明度の設定、ペイント、シェーディング、陰影の描画、透明レイヤー、色管理、アンチエイリアスレンダリング、PDF 文書の生成、PDF メタデータなどにアクセスする機能を使用できます。可能であればいつでも、Quartz 2D はグラフィックスハードウェアの力を活用します。
Mac OS X では、Quartz 2D は Core Image、Core Video、OpenGL、および QuickTime といった他のすべてのグラフィックスおよびイメージングテクノロジーと連携できます。QuickTime 関数GraphicsImportCreateCGImage を使用して、QuickTime グラフィックスインポータから Quartz でイメージを作成することができます。詳細については、QuickTime Framework リファレンス を参照してください。Mac OS X で Quartz 2D と Core Image 間でデータを移動 では、イメージ処理をサポートするフレームワークである Core Image にイメージを提供する方法が説明されています。
同様に、iOS では、Quartz 2D は、Core Animation、OpenGL ES、UIKit クラスなど、利用可能なすべてのグラフィックスおよびアニメーション技術を使用して動作します。
ページ
Quartz 2D は、イメージングに ペインターのモデル を使用します。ペインターのモデルでは、連続する各描画操作は、しばしば ページ と呼ばれる出力"キャンバス" に"ペイント" のレイヤーを適用します。ページ上のペイントは、追加の描画操作でさらにペイントを重ね塗りすることによって変更できます。ページに描画されたオブジェクトは、ペイントを重ね塗りする以外は変更できません。このモデルでは、少数の強力なプリミティブから非常に洗練されたイメージを構築することができます。
図 1-1 に、ペインターのモデルの仕組みを示します。図の上部のイメージを取得するには、左の図形が最初に描画された後に、塗りつぶされた形が描画されます。塗りつぶされた形は、最初の形に重なり、最初の形の周囲を除くすべてを覆い隠します。図形の下部では、図形が逆の順序で描かれ、最初に塗りつぶした形が描かれています。ご覧のように、ペインターのモデルでは描画順序が重要です。
図 1-1 ペインターのモデル
ページは実際の用紙(出力装置がプリンタの場合) です。それは、(出力デバイスが PDF ファイルであれば) 仮想紙であってもよいでしょう。それはビットマップ画像であってもよいでしょう。ページの正確な性質は、使用する特定のグラフィックスコンテキストによって異なります。
描画先:グラフィックスコンテキスト
グラフィックスコンテキスト は、Quartz が PDF ファイル、ビットマップ、ディスプレイ上のウィンドウなどの出力デバイスにイメージを描画するために使用する情報をカプセル化する不透明データ型(CGContextRef) です。グラフィックスコンテキスト内の情報は、グラフィックス描画パラメータと、ページ上のペイントのデバイス特有の表現とを含みます。Quartz のすべてのオブジェクトは、グラフィックスコンテキストに描画されるか、含まれます。
図 1-2 に示すように、グラフィックスコンテキストを描画先と考えることができます。Quartz を使用して描画する場合、デバイス固有のすべての特性は、使用する特定の型のグラフィックスコンテキスト内に含まれます。言い換えれば、Quartz 描画ルーチンの同じシーケンスに異なるグラフィックスコンテキストを提供するだけで、同じ画像を別のデバイスに描画することができます。デバイス固有の計算を行う必要はありません。Quartz はあなたのためにそれを行います。
図 1-2 Quartz の描画先
これらのグラフィックスコンテキストはアプリケーションで使用できます。
- ビットマップグラフィックスコンテキスト では、RGB カラー、CMYK カラー、またはグレースケールをビットマップにペイントできます。ビットマップ はピクセルの長方形の配列(またはラスタ) であり、各ピクセルは画像内の点を表します。ビットマップイメージは、サンプリングイメージ とも呼ばれます。ビットマップグラフィックスコンテキストの作成 を参照してください。
- PDF グラフィックスコンテキスト を使用すると、PDF ファイルを作成できます。PDF ファイルでは、描画は一連のコマンドとして保存されます。PDF ファイルとビットマップにはいくつかの重要な違いがあります。
- PDF ファイルは、ビットマップと異なり、複数のページを含むことがあります。
- 別のデバイス上の PDF ファイルからページを描画すると、そのイメージはそのデバイスの表示特性に合わせて最適化されます。
- PDF ファイルは本質的に解像度に依存しません。イメージの詳細を犠牲にすることなく、描画されるサイズを無限に増減できます。ビットマップイメージのユーザが知覚する品質は、ビットマップが表示されるべき解像度に結び付けられます。
- ウィンドウグラフィックスコンテキスト は、ウィンドウに描画するために使用できるグラフィックスコンテキストです。Quartz 2D はグラフィックスエンジンであり、ウィンドウ管理システムではないため、アプリケーションフレームワークの 1 つを使用してウィンドウのグラフィックスコンテキストを取得することに注意してください。詳細については、Mac OS X でのウィンドウグラフィックスコンテキストの作成 を参照してください。
- レイヤーコンテキスト(CGLayerRef) は、別のグラフィックスコンテキストに関連付けられたオフスクリーン描画先です。レイヤーを作成したグラフィックスコンテキストにレイヤーを描画するときに最適なパフォーマンスが得られるように設計されています。オフスクリーン描画では、ビットマップグラフィックスコンテキストよりもレイヤーコンテキストを選択する方がはるかに優れています。Core Graphics のレイヤー描画 を参照してください。
- Mac OS X で印刷する場合は、印刷フレームワークによって管理される PostScript グラフィックスコンテキスト にコンテンツを送信します。詳細については、印刷用のグラフィックスコンテキストの取得 を参照してください。
PDF グラフィックスコンテキストの作成 を参照してください。
Quartz 2D 不透明(Opaque) データ型
Quartz 2D API は、グラフィックスコンテキストに加えて、さまざまな不透明なデータ型を定義します。API は Core Graphics フレームワークの一部であるため、データ型とそれを操作するルーチンは CG プレフィックスを使用します。
Quartz 2D は、特定の描画出力を実現するためにアプリケーションが操作する不透明なデータ型からオブジェクトを作成します。図 1-3 に、Quartz 2D が提供する 3 つのオブジェクトに描画操作を適用したときに得られる結果の種類を示します。例えば:
- PDF ページオブジェクトを作成し、回転操作をグラフィックスコンテキストに適用し、Quartz 2D にグラフィックスコンテキストにページを描画するように要求することで、PDF ページを回転して表示することができます。
- パターンを作成するには、パターンオブジェクトを作成し、パターンを構成するシェイプを定義し、パターンをグラフィックスコンテキストに描画するときにペイントとして使用するように Quartz 2D を設定します。
- シェーディングオブジェクトを作成し、シェーディングの各点で色を決定する関数を提供し、シェーディングを塗りつぶし色として使用するよう Quartz 2D に依頼することで、軸方向または放射状シェーディングで領域を塗りつぶすことができます。
図 1-3 不透明データ型は、Quartz 2D の描画プリミティブの基礎です
Quartz 2D で利用できる不透明データ型には、以下のものがあります。
- CGPathRef:ベクターグラフィックスで塗りつぶしやストロークするためのパスを作成するために使用されます。パス (Paths) を参照してください。
- CGImageRef は、提供するサンプルデータに基づいてビットマップイメージとビットマップイメージマスクを表すために使用されます。ビットマップイメージとイメージマスク を参照してください。
- CGLayerRef は、繰り返し描画(背景やパターンなど) やオフスクリーン描画に使用できる描画レイヤーを表します。Core Graphics のレイヤー描画 を参照してください。
- CGPatternRef は、繰り返し描画に使用されます。パターン を参照してください。
- CGShadingRef と CGGradientRef は、グラデーションを描画するために使用されます。グラデーション を参照してください。
- CGFunctionRef は、任意の数の浮動小数点引数をとるコールバック関数を定義するために使用されます。このデータ型は、シェーディング用のグラデーションを作成するときに使用します。グラデーション を参照してください。
- CGColorRef と CGColorSpaceRef は、色を解釈する方法を Quartz に知らせるために使用されます。色と色空間 を参照してください。
- CGImageSourceRef と CGImageDestinationRef は、Quartz との間でデータを出し入れして移動するために使用します。Quartz 2D でのデータ管理 および イメージ I/O プログラミングガイド を参照してください。
- CGFontRef は、テキストを描画するために使用されます。テキスト を参照してください。
- CGPDFDictionaryRef、CGPDFObjectRef、CGPDFPageRef、CGPDFStream、CGPDFStringRef、および CGPDFArrayRef は、PDFメタデータへのアクセスを提供します。PDF 文書の作成、表示、および変換 を参照してください。
- CGPDFScannerRef と CGPDFContentStreamRef は、PDF メタデータを解析します。PDF 文書の解析 を参照してください。
- CGPSConverterRef は、PostScript を PDF に変換するために使用されます。iOS では利用できません。PostScript 変換 を参照してください。
グラフィックス状態
Quartz は、現在のグラフィックス状態 のパラメータに従って描画操作の結果を変更します。グラフィックス状態には、描画ルーチンの引数として他に使用されるパラメータが含まれています。グラフィックスコンテキストに描画するルーチンは、グラフィックス状態を調べて、その結果のレンダリング方法を決定します。たとえば、塗りつぶしの色を設定する関数を呼び出すと、現在のグラフィックス状態に格納されている値が変更されます。現在のグラフィックス状態の他の一般的に使用される他の要素には、線の幅、現在位置、およびテキストのフォントサイズが含まれます。
グラフィックスコンテキストには、グラフィックス状態のスタックを含みます。Quartz がグラフィックスコンテキストを作成するとき、スタックは空です。グラフィックス状態を格納すると、Quartz は現在のグラフィックス状態のコピーをスタック上にプッシュします。グラフィックス状態を復元すると、Quartz はグラフィックス状態をスタックの一番上からポップします。ポップされた状態は、現在のグラフィックス状態になります。
現在のグラフィックス状態を格納するには、CGContextSaveGState 関数を使用して、現在のグラフィックス状態のコピーをスタック上にプッシュします。以前に格納したグラフィックス状態を復元するには、CGContextRestoreGState 関数を使用して、現在のグラフィックス状態をスタックの一番上にあるグラフィックス状態と置き換えます。
現在の描画環境のすべての側面がグラフィックス状態の要素であるわけではないことに注意してください。たとえば、現在のパスはグラフィックス状態の一部とはみなされないため、CGContextSaveGState 関数を呼び出しても格納されません。この関数を呼び出すときに格納されるグラフィックス状態パラメータを、表 1-1 にリストします。
表 1-1 グラフィックス状態に関連するパラメータ
パラメータ | この章で議論 |
---|---|
現在の変換マトリックス(CTM) | 変換 |
クリッピングエリア | パス (Paths) |
線:幅、結合、頂点、破線、留め継ぎ制限 | パス (Paths) |
カーブ推定精度(平坦度) | パス (Paths) |
アンチエイリアスの設定 | グラフィックスコンテキスト |
色:塗りつぶしとストロークの設定 | 色と色空間 |
アルファ値(透明度) | 色と色空間 |
レンダリングの意図 | 色と色空間 |
色空間:塗りつぶしとストロークの設定 | 色と色空間 |
テキスト:フォント、フォントサイズ、文字間隔、テキスト描画モード | テキスト |
ブレンドモード | パス (Paths) 及び ビットマップイメージとイメージマスク |
Quartz 2D 座標系
座標系は、図 1-4 に示したように、ページ上に描画されたオブジェクトの位置とサイズを表すために使用される場所の範囲を定義します。グラフィックスの位置とサイズをユーザー空間座標系で指定するか、より簡単に ユーザー空間 を指定します。座標は浮動小数点値として定義されます。
図 1-4 Quartz 座標系
異なるデバイスは、異なる基礎となるイメージ能力を有するため、グラフィックスの位置およびサイズはデバイスに依存しない方法で定義されなければなりません。例えば、スクリーン表示装置は 1 インチ当たり 96 ピクセル以下を表示でき、プリンタは 300 ピクセル/インチを表示することができます。デバイスレベル(この例では 96 ピクセルまたは 300 ピクセル) で座標系を定義すると、その空間に描画されたオブジェクトは、目に見える歪みなしに他のデバイスで再現することはできません。それらは大きすぎるか小さすぎるでしょう。
Quartz は、現在の変換マトリックス、つまり CTM を使用して、出力デバイス/デバイス空間の座標系にユーザー空間をマッピングする別の座標系でデバイスの独立性を実現します。行列 は、関連する方程式の集合を効率的に記述するために使用される数学的構成です。現在の変換行列は、アフィン変換 と呼ばれる特定の型の行列で、平行移動、回転、および スケーリング 操作(座標系を移動、回転、サイズ変更する計算) を適用して、ある座標空間から別の座標空間に点をマッピングします。
現在の変換行列には 2 次的な目的があります。オブジェクトの描画方法を変換することができます。たとえば、45 度回転した箱を描画するには、箱を描画する前にページの座標系(CTM) を回転させます。Quartz は、回転した座標系を使用して出力デバイスに描画します。
ユーザ空間内の点は座標系の対(x、y) で表され、x は水平軸(左右) に沿った位置を表し、y は垂直軸(上下) を表します。ユーザー座標空間の 原点 は、点(0,0) です。図 1-4 に示すように、原点はページの左下隅にあります。Quartz のデフォルトの座標系では、x 軸はページの左から右に移動するにつれて増加します。y 軸はページの下から上に向かって値が大きくなります。
技術によっては、Quartz が使用するものとは異なるデフォルトの座標系を使用してグラフィックスコンテキストを設定するものがあります。Quartz に対して、そのような座標系は 変更された座標系 であり、いくつかの Quartz 描画操作を実行するときに補償されなければなりません。最も一般的な変更された座標系は、原点をコンテキストの左上隅に置き、y 軸をページの下端に向けるよう変更します。使用されるこの特定の座標系が表示される少ない場所は、次のとおりです。
- Mac OS X で、isFlipped メソッドをオーバーライドして YES を返す NSView のサブクラス。
- iOS では、UIView によって返される描画コンテキスト。
- iOS では、UIGraphicsBeginImageContextWithOptions 関数を呼び出して作成された描画コンテキスト。
UIKit が修正された座標系を持つ Quartz 描画コンテキストを返す理由は、UIKit が異なるデフォルトの座標規約を使用するためです。作成した Quartz コンテキストに変換を適用して、その変換規則に一致するようにします。アプリケーションが同じ描画ルーチンを使用して UIView オブジェクトと PDF グラフィックスコンテキスト(Quartz によって作成され、デフォルトの座標系を使用する) の両方に描画したい場合は、PDF グラフィックスコンテキストが、同じ変更された座標系を受け取るように適用しなければなりません。これを行うには、原点を PDF コンテキストの左上隅に変換し、y 座標を -1 でスケールする変換を適用します。
スケーリング変換を使用して y 座標を無効にすると、Quartz 描画のいくつかの規則が変更されます。たとえば、CGContextDrawImage を呼び出してイメージをコンテキストに描画すると、イメージは目的先に描画されるときに変換によって変更されます。同様に、パス描画ルーチンは、弧が デフォルト の座標系で時計回りまたは反時計回りのどちらの方向に描かれるかを指定するパラメータを受け取ります。座標系が変更された場合、イメージが鏡に反映されたかのように、結果も変更されます。図 1-5 では、同じパラメータを Quartz に渡すと、デフォルトの座標系での時計回りの弧が得られ、y 座標が変換によって無視された後に反時計回りの弧が得られます。
図 1-5 座標系を変更すると、鏡像が作成されます。
アプリケーションには、変換が適用されているコンテキストに対して行うすべての Quartz 呼び出しを調整する責任があります。たとえば、イメージまたは PDF をグラフィックスコンテキストに正しく描画するには、アプリケーションはグラフィックスコンテキストの CTM を一時的に調整する必要があります。iOS では、UIImage オブジェクトを使用して作成した CGImage オブジェクトを包み込むと、CTM を変更する必要はありません。UIImage オブジェクトは、UIKit によって適用された、変更された座標系を自動的に補正します。
メモリー管理:オブジェクトの所有権
Quartz は、オブジェクトが参照カウントされる Core Foundation メモリ管理モデルを使用します。作成されると、Core Foundation オブジェクトは参照カウント 1 で開始されます。オブジェクトを保持する関数を呼び出して参照カウントを増分し、オブジェクトを解放する関数を呼び出して参照カウントを減分します。参照カウントが 0 に減分されると、オブジェクトは解放されます。このモデルは、オブジェクトが他のオブジェクトへの参照を安全に共有できるようにします。
心に留めておくべきいくつかの簡単なルールがあります:
- オブジェクトを作成またはコピーする場合、オブジェクトを所有しているため、オブジェクトを解放しなければなりません。つまり、一般に、名前に"Create" または"Copy" という単語を含む関数からオブジェクトを取得する場合は、そのオブジェクトの用事が終了したときにそのオブジェクトを解放しなければなりません。それ以外の場合は、メモリリークが発生します。
- 名前に"Create" または"Copy" という単語を含まない関数からオブジェクトを取得した場合は、そのオブジェクトへの参照を所有しておらず、解放してはいけません。オブジェクトは将来、ある時点で所有者によって解放されます。
- あなたがオブジェクトを所有しておらず、オブジェクトを保持しておく必要がある場合は、オブジェクトを保持して解放しなければなりません。オブジェクトに固有の Quartz 2D 関数を使用して、そのオブジェクトを保持および解放します。たとえば、CGColorspace オブジェクトへの参照を受け取った場合は、CGColorSpaceRetain および CGColorSpaceRelease 関数を使用して、必要に応じてオブジェクトを保持および解放します。また、Core Foundation の関数 CFRetain と CFRelease を使用することもできますが、これらの関数に NULL を渡さないように注意しなければなりません。
前の章 次の章