目次 | 前の項目 | 次の項目 | Java 2D API |
Java 2DTM API を使ってグラフィックオブジェクトをレンダリングするには、Graphics2D コンテキストを設定してから、Graphics2D レンダリングメソッドにグラフィックオブジェクトを渡します。Graphics2D コンテキストを構成する状態属性を変更することで、次の操作が可能です。
Graphics2D では、グラフィックスコンテキストの属性を追加または変更するためのメソッドがいくつか定義されています。 大部分のメソッドは、Paint オブジェクトや Stroke オブジェクトなど、特定の属性を表すオブジェクトを受け取ります。Graphics2D コンテキストは、このような属性オブジェクトの「参照」を保持します。 属性オブジェクトは複製されません。 Graphics2D コンテキストに含まれる属性オブジェクトを変更する場合は、適切な set メソッドを呼び出して、コンテキストに通知する必要があります。 レンダリング操作の間に属性オブジェクトを変更すると、予測できない動作をしたり、場合によっては動作が不安定になります。
グラフィックオブジェクトのレンダリングでは、幾何形状、イメージ、および属性の情報がまとめられて、ディスプレイ上で変更する必要のあるピクセル値が算出されます。Shape のレンダリング処理は、4 つのステップに分けることができます。
テキストのレンダリングは、Shape のレンダリングとほぼ同じです。 テキストは個別のグリフとしてレンダリングされて、グリフはそれぞれが Shape です。 唯一の違いは、レンダリングの前に、テキストに適用される Font を判別し、Font から適切なグリフを取得する必要があることです。イメージの処理はテキストや図形と異なり、変換操作とクリッピング操作はイメージのバウンディングボックスに対して行われます。 色の情報はイメージ自体から取り出されて、イメージのピクセルがレンダリング面に合成される際は、色情報のアルファチャネルがそのときの Composite 属性とともに使われます。
Java 2D API では、速度と品質のどちらを優先してオブジェクトをレンダリングするか指定できます。 優先情報は、Graphics2D コンテキストの RenderingHints 属性を使ってヒントとして指定します。 レンダリングモードの変更に対応していないプラットフォームもあるため、指定したレンダリングヒントが必ず使われるとは限りません。RenderingHints クラスは、次の種類のヒントをサポートしています。
Graphics2D コンテキストの RenderingHints 属性を設定または変更するには、setRenderingHints を呼び出します。 ヒントをデフォルトに設定すると、プラットフォームでのレンダリングのデフォルト設定が使われます。
GeneralPath オブジェクトのような Shape のストロークを描画することは、GeneralPath のセグメントに沿って論理的なペンを走らせることに相当します。 Graphics2D の Stroke 属性は、ペンによって描画される軌跡の特性を定義するものです。Graphics2D コンテキストのストローク属性を定義するには、BasicStroke オブジェクトを使います。 BasicStroke では、線の幅、線端のスタイル、セグメントの接合スタイル、破線パターンなどの特性が定義されています。 Graphics2D コンテキストの Stroke 属性を設定または変更するには、setStroke メソッドを呼び出します。
たとえば、図 2-3 の最初のイメージは角を付けた接続スタイルを使っており、2 番目のイメージは丸めた接続スタイル、丸めた線端スタイル、および破線パターンを使っています。
Stroke 属性を使う Graphics2D レンダリングメソッドは、draw、drawArc、drawLine、drawOval、drawPolygon、drawPolyline、drawRect、および drawRoundRect です。 これらのメソッドを呼び出すと、指定した Shape の輪郭がレンダリングされます。 Stroke 属性は線の特性を定義し、Paint 属性はペンによって描画される軌跡の色とパターンを定義するものです。たとえば、draw(myRectangle) を呼び出すと、次の処理が行われます。
図 2-4 は、この処理を具体例で示したものです。
Graphics2D コンテキストの塗りつぶし属性は、Paint オブジェクトで表されます。 Graphics2D コンテキストに Paint オブジェクトを追加するには、setPaint メソッドを呼び出します。Shape またはグリフを描画すると (Graphics2D.draw、Graphics2D.drawString)、オブジェクトの輪郭線を描画する Shape の内側にあるすべてのピクセルに、Paint が適用されます。 Shape を塗りつぶすと (Graphics2D.fill)、Shape の輪郭の内側にあるすべてのピクセルに、Paint が適用されます。
単純な均一の塗りつぶしは、setColor メソッドで設定できます。 Color は、Paint インタフェースのもっとも簡単な実装です。
グラデーションやテクスチャーのようなさらに複雑なスタイルで Shape を塗りつぶすには、Java 2D の Paint インタフェースの GradientPaint クラスと TexturePaint クラスを使います。 単純な一色塗りで複雑な塗りつぶしを行おうとすると時間のかかる作業になりますが、これらのクラスを使うと手間のかかる作業は必要なくなります。 図 2-5 に示す 2 種類の塗りつぶしは、GradientPaint と TexturePaint で簡単に定義できます。
fill を呼び出して Shape をレンダリングすると、システムでは次の処理が行われます。
バッチ処理 ピクセルを効率よく処理するため、Java 2D API はバッチでピクセルを処理します。 特定の走査線の連続したピクセル群またはピクセルのブロックをバッチ処理できます。 このバッチ処理は、2 つのステップで行われます。
- Paint オブジェクトの createContext メソッドを呼び出し、PaintContext を作成します。 PaintContext には、現在のレンダリング操作についてのコンテキスト情報と、色の生成に必要な情報が格納されます。 createContext メソッドには、塗りつぶしの対象となっているグラフィックスオブジェクトのユーザ空間とデバイス空間におけるバウンディングボックス、色の生成に使われる ColorModel、およびユーザ空間からデバイス空間へのマッピングで使われる変換が渡されます。 任意の ColorModel をサポートできない Paint オブジェクトもあるので、ColorModel はヒントとして扱われます。 ColorModel の詳細については、「カラー」を参照してください。
- getColorModel メソッドを呼び出して、生成された塗りつぶし色の ColorModel を PaintContext から取得します。
次に、getRaster メソッドを繰り返し呼び出して、各バッチの実際の色データを含む Raster を取得します。 この情報はレンダリングパイプラインの次の段階に渡されて、そこでは、生成された色が現在の Composite オブジェクトを使って描画されます。
「クリッピングパス」は、Shape または Image の中のレンダリングが必要な部分を示すものです。 Graphics2D コンテキストにクリッピングパスが含まれている場合、Shape または Image で実際にレンダリングされるのは、クリッピングパスの内側にある部分だけです。Graphics2D コンテキストにクリッピングパスを追加するには、setClip メソッドを呼び出します。 任意の Shape を使って、クリッピングパスを定義できます。
クリッピングパスを変更するには、setClip を呼び出して新しいパスを指定するか、あるいは clip を呼び出して、古いクリッピングパスと新しい Shape の交差している部分を新しいクリッピングパスにします。
Graphics2D コンテキストに含まれている変換は、レンダリングでユーザ空間からデバイス空間にオブジェクトを変換するときに使われます。 回転や拡大縮小など、これ以外の変換を行うには、その変換を Graphics2D コンテキストに追加します。 追加した変換は、レンダリングの際に適用される変換のパイプラインの一部になります。Graphics2D では、Graphics2D コンテキストの変換を変更する方法がいくつか提供されています。 もっとも簡単な方法は、rotate、scale、shear、translate などのGraphics2D 変換メソッドを呼び出すことです。 レンダリングで適用する変換の特性を指定すると、Graphics2D が自動的に適切な変更を行います。
現在の Graphics2D の変換に、AffineTransform を明示的に「連結」することもできます。 AffineTransform は、グラフィックスプリミティブのグループに対し、平行移動、拡大縮小、回転、変形などの線形変換を行います。 既存の変換に新しい変換を連結すると、指定した最後の変換が「最初に」適用されます。 現在の変換に新しい変換を連結するには、Graphics2D.transform に AffineTransform を渡します。
Graphics2D クラスには setTransform メソッドも含まれますが、既存の変換に別の座標変換を連結するためにこのメソッドを使用しないでください。 setTransform メソッドは Graphics2D オブジェクトの現行の変換を上書きします。この機能は、次のような操作を行う場合に必要です。
setTransform メソッドは、変換したグラフィックス、テキスト、またはイメージのレンダリング後に、 Graphics2D オブジェクトを元の変換に戻す場合に使用します。
- プリンタの解像度に合わせてスケーリング変換を行う。
- ゼロ以外の変換で、親の原点から JComponent をペイントする。
- コンポーネントを拡大して見やすくする。
- Graphics2D オブジェクトの供給者が、レンダリングの変換で効果を得る可能性がある他のすべての状況。
// Get the current transform. AffineTransform aT = g2d.getTransform(); // Apply a transformation and render. g2d.transform(...); g2d.draw(...); // Reset the original transform. g2d.setTransform(aT);Graphics2D では、パラメータとして AffineTransform を受け取る形式の drawImage メソッドも提供されています。 このメソッドを使うと、変換のパイプラインを変更しなくても、イメージオブジェクトを描画するときに目的の変換を適用できます。 イメージは、Graphics2D コンテキストの現在の変換に新しい変換を連結した場合と同じように描画されます。
アフィン変換 Java 2D API では、AffineTransform という変換クラスが提供されています。 AffineTransform を使って、レンダリングの際のテキスト、図形、およびイメージの変換が行われます。 Font オブジェクトに変換を適用し、新しいフォント派生を作ることもできます。 詳細については、「フォント派生の作成」を参照してください。アフィン変換は、グラフィックスプリミティブのグループに対して線形の変換を行います。 直線は直線に、平行線は平行線に、常に変換されますが、点の間の距離および平行ではない線の間の角度は変わります。
アフィン変換は、次の形式の 2 次元行列に基づいて行われます。
この場合、次の 2 つの式が成立します。 および 変換を組み合わせることで、オブジェクトに適用できる一連の変換群、つまり変換の「パイプライン」を効果的に作成できます。 この組み合わせのことを「連結」と呼びます。 AffineTransform.concatenate などの既存の変換に新しい変換を連結すると、最後に指定した変換が「最初」に適用されます。 既存の変換に、新しい変換を「前連結」することもできます。 この場合は、最後に指定した変換が「最後」に適用されます。
前連結は、ユーザ空間ではなくデバイス空間に関係する変換を行うために使います。 たとえば、絶対ピクセル空間に関係する変換を実行するには、AffineTransform.preConcatenate を使います。
AffineTransform では、AffineTransform オブジェクトを作成するための便利なメソッド群が提供されています。
これらのメソッドを使って作成する変換の特性を指定すると、AffineTransform が適切な変換行列を生成します。 変換行列の要素を直接指定して、AffineTransform を作成することもできます。
2 つのグラフィックオブジェクトが重なる場合、重なった部分のピクセルをどのような色でレンダリングするかを決める必要があります。 たとえば、赤い矩形と青い矩形を重ねる場合、2 つの図形が共有するピクセルは、赤、青、または 2 つの色の任意の組み合わせでレンダリングすることになります。 重なる領域のピクセルの色により、どちらの矩形が上になっていて、どの程度透けて見えるかが決まります。 重なるオブジェクトで共有されているピクセルをどのような色でレンダリングするか決める処理を、「重ね合わせ処理」と呼びます。Java 2D の合成処理モデルの基礎になるのは、 Composite と CompositeContext という 2 つのインタフェースです。
使う合成のスタイルを指定するには、setComposite メソッドを呼び出して、Graphics2D コンテキストに AlphaComposite オブジェクトを追加します。 Composite インタフェースの実装である AlphaComposite では、さまざまな合成スタイルがサポートされています。 このクラスのインスタンスは、既存の色と新しい色を混合する方法を記述した合成の規則を具体的に表しています。
AlphaComposite クラスで使われるもっとも一般的な重ね合わせ規則の 1 つは SRC_OVER で、これは、新しい色 (ソース色) を既存の色 (デスティネーション色) の上に混合するように指定するものです。
AlphaComposite の合成規則
説明
例CLEAR
クリア
DEST_IN
デスティネーションが内側
DEST_OUT
デスティネーションが外側
DEST_OVER
デスティネーションが上
SRC
ソース
SRC_IN
ソースが内側
SRC_OUT
ソースが外側
SRC_OVER
ソースが上
色の「アルファ」値は透明度の単位で、色を重ねたときに前にレンダリングされている色がどの程度遮られるかを、パーセントで示します。 不透明な色 (アルファ = 1.0) は下になっている色をまったく通さず、透明な色 (アルファ = 0.0) は下の色を完全に通します。テキストと Shape のレンダリングでは、アルファ値は Graphics2D コンテキストの Paint 属性から導出されます。 Shape とテキストが平滑化される場合は、Graphics2D コンテキストの Paint 属性から得られるアルファ値は、ラスタ化されたパスからのピクセルカバレージ情報と結合されます。 イメージは独自のアルファ情報を保持しています。 詳細については、「透明度とイメージ」を参照してください。
AlphaComposite オブジェクトを作成する際に、アルファ値を追加指定できます。 この AlphaComposite オブジェクトを Graphics2D コンテキストに追加すると、追加したアルファ値により、レンダリングされるグラフィックオブジェクトの透明度が大きくなります。 つまり、各グラフィックオブジェクトのアルファ値に、AlphaComposite のアルファ値が掛けられます。
イメージには、イメージ内の各ピクセルに対する透明度の情報を持たせることができます。 「アルファチャネル」と呼ばれるこの情報は、イメージと既存の描画結果を混合するために、Graphics2D コンテキストの Composite オブジェクトと組み合わせて使われます。たとえば、図 2-6 に示すのは、異なる透明度情報を持つ 3 種類のイメージです。 どの場合も、イメージは青い矩形に重ねて表示されます。 この例では、Graphics2D コンテキストは、合成操作として SRC_OVER を使う AlphaComposite オブジェクトを含んでいるものとします。
最初のイメージでは、すべてのピクセルが完全に不透明 (犬の体) または完全に透明 (背景) になっています。 このような効果は、Web ページでよく使われます。 2 番目のイメージでは、犬の体の全ピクセルを不透明ではない一定のアルファ値でレンダリングすることにより、青い背景が透けて見えます。 3 番目のイメージでは、犬の顔の周囲のピクセルは完全に不透明 (アルファ = 1.0) ですが、顔から離れるに従って、ピクセルのアルファ値は徐々に小さくなっています。