目次 | 前へ | 次へ

第 2 章

Graphics2D を使ったレンダリング

java.awt.Graphics を継承する Graphics2D では、図形、テキスト、およびイメージの表示について制御できる内容が、一段と高度なものになっています。Java 2D™ のレンダリング処理は、Graphics2D オブジェクトとその状態属性を使って制御します。

Graphics2D の状態属性には線のスタイルや変換などがあり、グラフィックオブジェクトがレンダリングされるときに適用されます。Graphics2D に関する状態属性の集合を、Graphics2D コンテキストと呼びます。テキストや図形、イメージをレンダリングするには、Graphics2D コンテキストを設定してから、drawfill などの Graphics2D レンダリングメソッドを呼び出します。

2.1 インタフェースとクラス

次の表は、Graphics2D コンテキストに関連して使うインタフェースとクラスの一覧です。状態属性を表すクラスも含まれています。これらのほとんどのクラスは、java.awt パッケージに含まれています。

インタフェース 説明
Composite 基になるグラフィックス領域に描画プリミティブを合成するためのメソッドを定義します。AlphaComposite によって実装されます。
CompositeContext 合成操作のためのカプセル化されて最適化された環境を定義します。プログラムで独自の合成規則を実装するときに使われます。
Paint スーパークラス:Transparency draw 操作または fill 操作での色を定義します。ColorGradientPaint、および TexturePaint によって実装されます。
PaintContext ペイント操作のためのカプセル化されて最適化された環境を定義します。プログラムで独自のペイント操作を実装するときに使われます。
Stroke レンダリングされる Shape の輪郭線を囲む Shape を生成します。BasicStroke によって実装されます。

 

クラス 説明
AffineTransform (java.awt.geom) 2 次元のアフィン変換を表します。ある 2 次元座標から別の 2 次元座標への線形マッピングを行います。
AlphaComposite インタフェース:Composite 図形、テキスト、イメージの基本的なアルファ合成規則を実装します。
BasicStroke インタフェース:Stroke Shape の輪郭線に適用される「ペンのスタイル」を定義します。
Color インタフェース:Paint Shape に均一な塗りつぶしを定義します。
GradientPaint インタフェース:Paint Shape にカラーの線形グラデーションの塗りつぶしパターンを定義します。この塗りつぶしパターンは、点 P1 の色 C1 から点 P2 の色 C2 まで変化します。
Graphics2D スーパークラス:Graphics 2 次元レンダリングの基本クラスです。元の java.awt.Graphics クラスを継承しています。
TexturePaint インタフェース:Paint テクスチャーまたはパターンを使った Shape の塗りつぶしを定義します。テクスチャーやパターンは、BufferedImage から生成されます。

2.2 レンダリングのコンセプト

Java 2D™ API を使ってグラフィックオブジェクトをレンダリングするには、Graphics2D コンテキストを設定してから、Graphics2D レンダリングメソッドの 1 つにグラフィックオブジェクトを渡します。

Graphics2D コンテキストを構成する状態属性を変更することで、次の操作が可能です。

Graphics2D では、グラフィックスコンテキストの属性を追加または変更するためのメソッドがいくつか定義されています。大部分のメソッドは、Paint オブジェクトや Stroke オブジェクトなど、特定の属性を表すオブジェクトを受け取ります。

Graphics2D コンテキストは、このような属性オブジェクトの参照を保持します。属性オブジェクトは複製されません。Graphics2D コンテキストに含まれる属性オブジェクトを変更する場合は、適切な set メソッドを呼び出して、コンテキストに通知する必要があります。レンダリング操作の間に属性オブジェクトを変更すると、予測できない動作をしたり、場合によっては動作が不安的になります。

2.2.1 レンダリングプロセス

グラフィックオブジェクトのレンダリングでは、幾何学的図形、イメージ、および属性の情報がまとめられて、ディスプレイ上で変更する必要のあるピクセル値が算出されます。

Shape のレンダリング処理は、4 つのステップに分けることができます。

テキストのレンダリングは、Shape のレンダリングとほぼ同じです。テキストは個別のグリフとしてレンダリングされて、グリフはそれぞれが Shape になります。唯一の違いは、レンダリングの前に、テキストに適用される Font を判別し、Font から適切なグリフを取得する必要があることです。

イメージの処理はテキストや図形と異なり、変換操作とクリッピング操作はイメージのバウンディングボックスに対して行われます。色の情報はイメージ自体から取り出されて、イメージのピクセルがレンダリング面に合成される際は、色情報のアルファチャネルがそのときの Composite 属性とともに使われます。

2.2.2 レンダリング品質の制御

Java 2D API では、速度と品質のどちらを優先してオブジェクトをレンダリングするか指定できます。優先情報は、Graphics2D コンテキストの RenderingHints 属性を使ってヒントとして指定します。レンダリングモードの変更に対応していないプラットフォームもあるため、指定したレンダリングヒントが必ず使われるとはかぎりません。

RenderingHints クラスは、次の種類のヒントをサポートしています。

Graphics2D コンテキストの RenderingHints 属性を設定または変更するには、setRenderingHints を呼び出します。ヒントをデフォルトに設定すると、プラットフォームでのレンダリングのデフォルト設定が使われます。

アンチエイリアス

グラフィックスプリミティブをラスタグラフィックスディスプレイ装置にレンダリングすると、エイリアス化のために縁がギザギザになる場合があります。弧や対角線の場合、直線や曲線の経路にもっとも近いピクセルをオンにして近似表現するので、ギザギザした表示になります。解像度の低い装置ではこの現象が特に顕著になるため、水平や垂直の線の滑らかな縁に対し、ギザギザの縁が際立って見えてしまいます。

アンチエイリアスは、オブジェクトの縁を滑らかにレンダリングするために使われる技法です。単純に直線や曲線にもっとも近いピクセルをオンにするのではなく、レンダリングされる形状によってカバーされる領域の大きさに比例して、周囲のピクセルの輝度が設定されます。これによって、オブジェクトの縁が鋭くなくなり、複数のピクセルにまたがってオンからオフへと移行するようになります。ただし、アンチエイリアスを行うと必要なコンピュータリソースが増えるため、レンダリングの速度が遅くなる場合があります。

.

この図は、拡大された文字の例です。

2.2.3 ストローク属性

GeneralPath オブジェクトのような Shape のストロークを描画することは、GeneralPath のセグメントに沿って論理的なペンを走らせることに相当します。Graphics2DStroke 属性は、ペンによって描画される軌跡の特性を定義するものです。

Graphics2D コンテキストのストローク属性を定義するには、A BasicStroke オブジェクトを使います。BasicStroke では、線の幅、線端のスタイル、セグメントの接合スタイル、破線パターンなどの特性が定義されています。Graphics2D コンテキストの Stroke 属性を設定または変更するには、setStroke を呼び出します。

このグラフィックスは、BasicStroke によってサポートされる、切り取り、丸め付き、または角付きの線端を含めた線端スタイルです。
図 2-1 BasicStroke によってサポートされる線端スタイル

このグラフィックスは、BasicStroke によってサポートされる、斜影、丸め、または角を付けた線端を含めた接続スタイルです。
図 2-2 BasicStroke によってサポートされる接続スタイル

たとえば、図 2-3 の最初のイメージは角を付けた接続スタイルを使っており、2 番目のイメージは丸めた接続スタイル、丸めた線端スタイル、および破線パターンを使っています。

この図が示す 2 つの星型のうち、最初の星型は角を付けた接続スタイルを使っており、2 番目の星型は丸めた接続スタイル、丸めた線端スタイル、および破線パターンを使っています
図 2-3 ストロークのスタイル

Stroke 属性を使う Graphics2D レンダリングメソッドは、drawdrawArcdrawLinedrawOvaldrawPolygondrawPolylinedrawRect、および drawRoundRect です。これらのメソッドを呼び出すと、指定した Shape の輪郭がレンダリングされます。Stroke 属性は線の特性を定義し、Paint 属性はペンによって描画される軌跡の色とパターンを定義するものです。

たとえば、draw(myRectangle) を呼び出すと、次の処理が行われます。

図 2-4 は、この処理を具体例で示したものです。

前の文で、このグラフィックスを説明しています。
図 2-4 図形のストローク

2.2.4 塗りつぶし属性

Graphics2D コンテキストの塗りつぶし属性は、Paint オブジェクトで表されます。Graphics2D コンテキストに Paint オブジェクトを追加するには、setPaint メソッドを呼び出します。

Shape またはグリフを描画すると (Graphics2D.drawGraphics2D.drawString)、オブジェクトの輪郭線を描画する Shape の内側にあるすべてのピクセルに、Paint が適用されます。Shape を塗りつぶすと (Graphics2D.fill)、Shape の外形の内側にあるすべてのピクセルに、Paint が適用されます。

単純な均一の塗りつぶしは、setColor メソッドで設定できます。Color は、Paint インタフェースのもっとも簡単な実装です。

グラデーションやテクスチャーのようなさらに複雑な描画スタイルで Shapes を塗りつぶすには、Java 2D の Paint インタフェースの GradientPaint クラスと TexturePaint クラスを使います。単純な 1 色塗りで複雑な塗りつぶしを行おうとすると時間のかかる作業になりますが、これらのクラスを使うと手間のかかる作業は必要なくなります。図 2-5 に示す 2 種類の塗りつぶしは、GradientPaintTexturePaint で簡単に定義できます。

この図が示す 2 つの図形のうち、最初の不規則な図形はグラデーションで塗りつぶされ、2 番目の矩形は格子縞テクスチャーで塗りつぶされています
図 2-5 複雑な塗りつぶしのスタイル

fill を呼び出して Shape をレンダリングすると、システムでは次の処理が行われます。

バッチ処理

ピクセルを効率よく処理するため、Java 2D API はバッチでピクセルを処理します。特定の走査線の連続したピクセル群またはピクセルのブロックをバッチ処理できます。このバッチ処理は、2 つのステップで行われます。

次に、getRaster メソッドを繰り返し呼び出して、各バッチの実際の色データを含む Raster を取得します。この情報はレンダリングパイプラインの次の段階に渡されて、そこでは、生成された色が現在の Composite オブジェクトを使ってレンダリングされます。

2.2.5 クリッピングパス

クリッピングパスは、Shape または Image の中のレンダリングが必要な部分を示すものです。Graphics2D コンテキストにクリッピングパスが含まれている場合、Shape または Image で実際にレンダリングされるのは、クリッピングパスの内側にある部分だけです。

Graphics2D コンテキストにクリッピングパスを追加するには、setClip メソッドを呼び出します。任意の Shape を使って、クリッピングパスを定義できます。

クリッピングパスを変更するには、setClip を呼び出して新しいパスを指定したり、あるいは clip を呼び出して、古いクリッピングパスと新しい Shape の交差している部分を新しいクリッピングパスにしたりします。

2.2.6 変換

Graphics2D コンテキストに含まれている変換は、レンダリングでユーザー空間からデバイス空間にオブジェクトを変換するときに使われます。回転や拡大縮小など、これ以外の変換を行うには、その変換を Graphics2D コンテキストに追加します。追加した変換は、レンダリングの際に適用される変換のパイプラインの一部になります。

Graphics2D では、Graphics2D コンテキストの変換を変更する方法がいくつか提供されています。もっとも簡単な方法は、次のいずれかの Graphics2D 変換メソッドを呼び出すことです。rotatescaleshear、または translate のいずれかです。レンダリングで適用する変換の特性を指定すると、Graphics2D が自動的に適切な変更を行います。

現在の Graphics2D の変換に、AffineTransform を明示的に連結することもできます。AffineTransform は、グラフィックスプリミティブのセットに対し、平行移動、拡大縮小、回転、変形などの線形変換を行います。既存の変換に新しい変換を連結すると、指定した最後の変換が最初に適用されます。現在の変換に新しい変換を連結するには、Graphics2D.transformAffineTransform を渡します。

Graphics2D クラスには setTransform メソッドも含まれますが、既存の変換に別の座標変換を連結する場合にはこのメソッドを使用しないでください。setTransform メソッドは Graphics2D オブジェクトの現行の変換を上書きします。この機能は、次のような操作を行う場合に必要です。

setTransform メソッドは、変換したグラフィックス、テキスト、またはイメージのレンダリング後に、Graphics2D オブジェクトを元の変換に戻す場合に使用します。

AffineTransform aT = g2d.getTransform(); 
g2d.transform(...);g2d.draw(...); 
g2d.setTransform(aT); 

Graphics2D では、パラメータとして AffineTransform を受け取る形式の drawImage メソッドも提供されています。このメソッドを使うと、変換のパイプラインを永続的に変更しなくても、イメージオブジェクトを描画するときに目的の変換を適用できます。イメージは、Graphics2D コンテキストの現在の変換に新しい変換を連結した場合と同じように描画されます。

アフィン変換

Java 2D API では、AffineTransform という変換クラスが提供されています。AffineTransforms を使って、レンダリングの際のテキスト、図形、およびイメージの変換が行われます。Font オブジェクトに変換を適用し、新しいフォント派生を作ることもできます。詳細については、「フォント派生の作成」を参照してください。

アフィン変換は、グラフィックスプリミティブのセットに対して線形の変換を行います。直線は直線に、平行線は平行線に、常に変換されますが、点の間の距離および平行ではない線の間の角度は変わります。

アフィン変換は、次の形式の 2 次元行列に基づいて行われます。

 

a、c および t のサブ x を含む先頭行を持つ 2 x 3 の行列。2 番目の行は、b、d および t のサブ y を含んでいます。ここでは、x プライムイコール a x プラス c y プラス t サブ x および y プライムイコール b x プラス d y プラス t サブ yです。

 

変換を組み合わせることで、オブジェクトに適用できる一連の変換群、つまり変換のパイプラインを効果的に作成できます。この組み合わせのことを連結と呼びます。AffineTransform.concatenate などの既存の変換に新しい変換を連結すると、最後に指定した変換が最初に適用されます。既存の変換に、新しい変換を前連結することもできます。この場合は、最後に指定した変換が最後に適用されます。

前連結は、ユーザー空間ではなくデバイス空間に関係する変換を行うために使います。たとえば、絶対ピクセル空間に関係する変換を実行するには、AffineTransform.preConcatenate を使います。

2.2.6.1 AffineTransform の作成

AffineTransform では、AffineTransform オブジェクトを作成するための便利なメソッド群が提供されています。

これらのメソッドを使って、作成する変換の特性を指定すると、AffineTransform が適切な変換行列を生成します。変換行列の要素を直接指定して、AffineTransform を作成することもできます。

2.2.7 重ね合わせ属性

2 つのグラフィックオブジェクトが重なる場合、重なった部分のピクセルをどのような色でレンダリングするかを決める必要があります。たとえば、赤い矩形と青い矩形を重ねる場合、2 つの図形が共有するピクセルは、赤、青、または 2 つの色の任意の組み合わせでレンダリングすることになります。重なる領域のピクセルの色により、どちらの矩形が上になっていて、どの程度透けて見えるかが決まります。重なるオブジェクトで共有されているピクセルをどのような色でレンダリングするか決める処理を、重ね合わせ処理と呼びます。

Java 2D の合成処理モデルの基礎になるインタフェースは、Composite および CompositeContext

使う合成のスタイルを指定するには、setComposite メソッドを呼び出して、Graphics2D コンテキストに AlphaComposite オブジェクトを追加します。Composite インタフェースの実装である AlphaComposite では、さまざまな合成スタイルがサポートされています。このクラスのインスタンスは、既存の色と新しい色を混合する方法を記述した合成の規則を具体的に表しています。

AlphaComposite クラスで使われるもっとも一般的な重ね合わせ規則の 1 つは SRC_OVER で、これは、新しい色 (ソース色) を既存の色 (デスティネーション色) の上に混合するように指定するものです。

AlphaComposite の合成規則 説明
CLEAR Clear
DEST_IN デスティネーションが内側
DEST_OUT デスティネーションが外側
DEST_OVER デスティネーションが上
SRC Source
SRC_IN ソースが内側
SRC_OUT ソースが外側
SRC_OVER ソースが上

2.2.7.1 透明度の管理

色のアルファ値は透明度の単位です。この値は、色を重ねたときに前にレンダリングされている色がどの程度透けて見えるかを、パーセントで示します。不透明な色 (alpha=1.0) は下になっている色をまったく通さず、透明な色 (alpha=0.0) は下の色を完全に通します。

テキストと Shapes のレンダリングでは、アルファ値は Graphics2D コンテキストの Paint 属性から導出されます。Shapes とテキストがアンチエイリアス処理される場合は、Graphics2D コンテキストの Paint 属性から得られるアルファ値は、ラスタ化されたパスからのピクセルカバレージ情報と結合されます。イメージは独自のアルファ情報を保持しています。詳細については、「透明度とイメージ」を参照してください。

AlphaComposite オブジェクトを作成する際に、アルファ値を追加指定できます。この AlphaComposite オブジェクトを Graphics2D コンテキストに追加すると、追加したアルファ値により、レンダリングされるグラフィックオブジェクトの透明度が大きくなります。つまり、各グラフィックオブジェクトのアルファ値に、AlphaComposite のアルファ値が掛けられます。

2.2.7.2 透明度とイメージ

イメージには、イメージ内の各ピクセルに対する透明度の情報を持たせることができます。アルファチャネルと呼ばれるこの情報は、イメージと既存の描画結果を混合するために、Graphics2D コンテキストの Composite オブジェクトと組み合わせて使われます。

たとえば、図 2-6 は、異なる透明度情報を持つ 3 種類のイメージです。どの場合も、イメージは青い矩形に重ねて表示されます。この例では、Graphics2D コンテキストは、合成操作として SRC_OVER を使う AlphaComposite オブジェクトを含んでいるものとします。

次のコンテキストでこのグラフィックスを説明します。
図 2-6 透明度とイメージ

最初のイメージでは、すべてのピクセルが完全に不透明 (犬の体) または完全に透明 (背景) になっています。このような効果は、Web ページでよく使われます。2 番目のイメージでは、犬の体の全ピクセルを不透明ではない一定のアルファ値でレンダリングすることにより、青い背景が透けて見えます。3 番目のイメージでは、犬の顔の周囲のピクセルは完全に不透明 (アルファ = 1.0) ですが、顔から離れるに従って、ピクセルのアルファ値は徐々に小さくなっています。

2.3 Graphics2D コンテキストの設定

レンダリングのための Graphics2D コンテキストを構成するには、Graphics2D の設定 (set) メソッドを使って、RenderingHintsStrokePaint、クリッピングパス、CompositeTransform などの属性を指定します。

2.3.1 レンダリングヒントの設定

RenderingHints オブジェクトは、オブジェクトをレンダリングする方法に関する設定をすべてカプセル化しています。Graphics2D コンテキストにレンダリングヒントを設定するには、RenderingHints オブジェクトを生成し、Graphics2D.setRenderingHints にそれを渡します。

レンダリングモードの変更をサポートしていないプラットフォームもあるので、レンダリングヒントを設定しても、特定のレンダリングアルゴリズムの使用が保証されるわけではありません。

次の例では、アンチエイリアスを有効にし、レンダリングのプリファレンスを quality に設定しています。

qualityHints = new               RenderingHints(RenderingHints.KEY_ANTIALIASING,               RenderingHints.VALUE_ANTIALIAS_ON); 
qualityHints.put(RenderingHints.KEY_RENDERING,               RenderingHints.VALUE_RENDER_QUALITY); 
g2.setRenderingHints(qualityHints); 

2.3.2 ストローク属性の指定

BasicStroke では、Shape の境界線に適用される特性が定義されています。これには、線の幅と破線パターン、線のセグメントの接続方法、および線端に適用される形状が含まれます。Graphics2D コンテキストにストローク属性を設定するには、BasicStroke オブジェクトを生成し、それを setStroke メソッドに渡します。

2.3.2.1 ストロークの幅の設定

ストロークの幅を設定するには、目的の幅を指定して BasicStroke オブジェクトを生成し、setStroke メソッドを呼び出します。

次の例では、ストロークの幅は 12 ポイントに設定し、接続と線端の形状にはデフォルトの設定を使っています。

wideStroke = new BasicStroke(12.0f); 
g2.setStroke(wideStroke); 

2.3.2.2 接続スタイルと線端スタイルの指定

接続スタイルと線端スタイルを設定するには、目的の属性を指定して BasicStroke オブジェクトを生成します。

次の例では、ストロークの幅は 12 ポイントに設定し、接続部と線端の形状には、デフォルトの設定ではなく、丸みを付けたスタイルを指定しています。

roundStroke = new BasicStroke(4.0f, BasicStroke.CAP_ROUND,              BasicStroke.JOIN_ROUND); 
g2.setStroke(roundStroke); 

2.3.2.3 破線パターンの設定

BasicStroke オブジェクトでは、複雑な破線パターンを簡単に定義できます。そのためには、BasicStroke オブジェクトを作るときに、破線パターンを制御する 2 つのパラメータを指定します。

次の例では、2 種類の破線パターンが線に適用されています。第 1 のパターンでは、ダッシュのサイズとダッシュ間の空白部のサイズは一定です。第 2 の破線パターンはさらに複雑で、6 つの要素を持つ配列を使って、破線パターンが定義されています。

float dash1[] = {10.0f}; 
BasicStroke bs = new BasicStroke(5.0f, BasicStroke.CAP_BUTT, 
                 BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f); 
g2.setStroke(bs); 
Line2D line = new Line2D.Float(20.0f, 10.0f, 100.0f, 10.0f); 
g2.draw(line); 
 
float[] dash2 = {6.0f, 4.0f, 2.0f, 4.0f, 2.0f, 4.0f}; 
bs = new BasicStroke(5.0f, BasicStroke.CAP_BUTT, 
     BasicStroke.JOIN_MITER, 10.0f, dash2, 0.0f); 
g2.setStroke(bs); 
g2.draw(line); 

どちらの破線パターンも破線のオフセットは 0 で、破線の描画は破線パターンの先頭から始まっています。この 2 種類の破線パターンを図 2-7 に示します。

.

最初の破線パターンは規則的で、2 番目の破線パターンは不規則です
図 2-7 破線パターン

2.3.3 塗りつぶし属性の指定

Graphics2D コンテキストの Paint 属性により、テキストと Shapes のレンダリング時に使われる塗りつぶしの色とパターンが決まります。

2.3.3.1 グラデーションを使った図形の塗りつぶし

GradientPaint クラスは、ある色から別の色へのグラデーションで図形を塗りつぶす簡単な方法を提供しています。GradientPaint を作るときに、開始の位置と色および終了の位置と色を指定します。塗りつぶしの色は、2 つの位置を結ぶ線に沿って、1 つの色から別の色まで、一定の比率で段階的に変化します。図 2-8 は、グラデーションを使った塗りつぶしの例です。

この図が示す 3 つの星型のうち、最初の星型は水平グラデーションを示し、2 番目の星型は傾斜した星型とグラデーションを示し、最後の星型は星型の内側にあるグラデーションポイントを示しています
図 2-8 グラデーションによる塗りつぶしの作成

図 2-8 の 3 番目の星型では、開始位置と終了位置が両方とも図形の内部にあります。グラデーションの向きを示す線を P1 より先に延長した部分にある点は、すべて開始位置の色で描画されて、グラデーション線を P2 より先に延長した部分にある点は、すべて終了位置の色で描画されます。

ある色から別の色へのグラデーションで図形を塗りつぶす場合は、次の手順で行います。

次の例では、青と緑のグラデーションで矩形を塗りつぶしています。

GradientPaint gp = new GradientPaint(50.0f, 50.0f, Color.blue 
                   50.0f, 250.0f, Color.green); 
g2.setPaint(gp); 
g2.fillRect(50, 50, 200, 200); 

2.3.3.2 テクスチャーを使った図形の塗りつぶし

TexturePaint クラスでは、繰り返しパターンで図形を塗りつぶす簡単な方法が提供されています。TexturePaint を作るときは、パターンとして使う BufferedImage を指定します。コンストラクタには、パターンの繰り返し単位を定義する矩形も渡します。図 2-9 はこの塗りつぶしの例です。

この図が示す 3 つのイメージのうち、最初のイメージは繰り返しパターン、2 番目のイメージは繰り返し単位を表す矩形、3 番目のイメージはテクスチャーで塗りつぶされた大きい矩形を示しています
図 2-9 テクスチャーを使った塗りつぶしの作成

テクスチャーによる図形の塗りつぶしは、次の手順で行います。

次の例では、バッファリングされたイメージから作られた簡単なテクスチャーで、矩形を塗りつぶしています。

// Create a buffered image texture patch of size 5x5 
BufferedImage bi = new BufferedImage(5, 5,   
                       BufferedImage.TYPE_INT_RGB); 
Graphics2D big = bi.createGraphics(); 
// Render into the BufferedImage graphics to create the texture 
big.setColor(Color.green); 
big.fillRect(0,0,5,5); 
big.setColor(Color.lightGray); 
big.fillOval(0,0,5,5); 
 
// Create a texture paint from the buffered image 
Rectangle r = new Rectangle(0,0,5,5); 
TexturePaint tp = new TexturePaint(bi,r,TexturePaint.NEAREST_NEIGHBOR); 
 
// Add the texture paint to the graphics context. 
g2.setPaint(tp); 
 
// Create and render a rectangle filled with the texture. 
g2.fillRect(0,0,200,200); 
} 

2.3.4 クリッピングパスの設定

クリッピングパスの定義は、次の手順で行います。

クリッピングパスの縮小は、次の手順で行います。

次の例では、まず楕円形でクリッピングパスを作成し、次に clip を呼び出してクリッピングパスを変更しています。

public void paint(Graphics g) { 
  Graphics2D g2 = (Graphics2D) g; 
 
// The width and height of the canvas 
  int w = getSize().width; 
  int h = getSize().height; 
  // Create an ellipse and use it as the clipping path 
  Ellipse2D e = new Ellipse2D.Float(w/4.0f,h/4.0f, 
                                    w/2.0f,h/2.0f); 
  g2.setClip(e); 
 
  // Fill the canvas. Only the area within the clip is rendered 
  g2.setColor(Color.cyan); 
  g2.fillRect(0,0,w,h); 
 
  // Change the clipping path, setting it to the intersection of 
  // the current clip and a new rectangle. 
  Rectangle r = new Rectangle(w/4+10,h/4+10,w/2-20,h/2-20); 
  g2.clip(r); 
 
  // Fill the canvas. Only the area within the new clip 
  // is rendered 
  g2.setColor(Color.magenta); 
  g2.fillRect(0,0,w,h); 
} 

2.3.5 Graphics2D の変換の設定

Shape、テキスト文字列、または Image を変換するには、レンダリングする前に、Graphics2D コンテキストの変換パイプラインに新しい AffineTransform を追加します。グラフィックオブジェクトをレンダリングすると、変換が適用されます。

たとえば、次は、矩形を 45 度回転させて描画する手順です。

次の例では、矩形をレンダリングするときに、AffineTransform のインスタンスを使って矩形を 45 度回転させています。

AffineTransform aT = g2.getTransform();Rectangle2D rect = new Rectangle2D.Float(1.0,1.0,2.0,3.0); 
AffineTransform rotate45 =   
  AffineTransform.getRotateInstance(Math.PI/4.0,0.0,0.0) 
g2.transform(rotate45); 
g2.draw(rect);g2.setTransform(aT); 

次の例では、AffineTransform を使って、中心点を軸にテキスト文字列を回転させています。

// Define the rendering transform 
AffineTransform at = new AffineTransform(); 
// Apply a translation transform to make room for the 
// rotated text. 
at.setToTranslation(400.0, 400.0); 
g2.transform(at); 
// Create a rotation transform to rotate the text 
at.setToRotation(Math.PI / 2.0); 
// Render four copies of the string “Java” at 90 degree angles 
for (int i = 0; i < 4; i++) { 
    g2.drawString(“Java”, 0.0f, 0.0f); 
    g2.transform(at); 
} 

イメージも同じ方法で変換できます。レンダリングされるグラフィックオブジェクトの種類に関係なく、レンダリングの際には Graphics2D コンテキストの変換が適用されます。

Graphics2D コンテキストで定義されている変換を変更しないで、イメージに変換を適用するには、drawImage メソッドに AffineTransform を渡します。

AffineTransform rotate45 =   
  AffineTransform.getRotateInstance(Math.PI/4.0,0.0,0.0) 
g2.drawImage(myImage, rotate45); 

Font に変換を適用して、見た目の異なる Font を作ることもできます。詳細については、「フォント派生の作成」を参照してください。

2.3.6 重ね合わせのスタイルの指定

AlphaComposite は、あるオブジェクトが別のオブジェクトと重なるときの色のレンダリング方法を決める、合成規則をカプセル化しています。Graphics2D コンテキストに合成スタイルを指定するには、AlphaComposite を作成し、それを setComposite メソッドに渡します。もっとも一般的に使われる合成スタイルは SRC_OVER です。

2.3.6.1 合成規則 SRC_OVER の使用方法

SRC_OVER の合成規則は、デスティネーションピクセルの上にソースピクセルを合成するもので、共有されるピクセルはソースピクセルの色になります。たとえば、青い矩形をレンダリングしてから、それと一部が重なる赤い矩形をレンダリングした場合、重なり合う部分の色は赤になります。つまり、最後にレンダリングされたオブジェクトが、いちばん上に表示されます。

合成規則 SRC_OVER の使用方法を次に示します。

合成オブジェクトがいったん設定されると、重なりを持つオブジェクトは指定されている重ね合わせ規則に従ってレンダリングされます。

2.3.6.2 合成オブジェクトの透明度の増加

AlphaComposite を使うと、アルファ値の定数を追加して指定できます。この値は、ソースピクセルのアルファ値に掛けられて、ソースピクセルの透明度が高くなります。

たとえば、50% の透明度でソースオブジェクトをレンダリングする AlphaComposite オブジェクトを作るには、アルファに .5 を指定します。

AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5f); 

次の例では、ソースを上に重ねるアルファ合成オブジェクトをアルファ値 .5 で作成し、グラフィックスコンテキストに追加しています。その結果、それ以降の図形は 50% の透明度でレンダリングされます。

public void paint(Graphics g) { 
  Graphics2D g2 = (Graphics2D) g; 
 
  g2.setColor(Color.red); 
  g2.translate(100,50); 
  // radians=degree * pie / 180 
  g2.rotate((45*java.lang.Math.PI)/180); 
  g2.fillRect(0,0,100,100); 
  g2.setTransform(new AffineTransform());  // set to identity 
  // Create a new alpha composite 
  AlphaComposite ac = 
      AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.5f); 
  g2.setComposite(ac); 
  g2.setColor(Color.green); 
  g2.fillRect(50,0,100,100); 
  g2.setColor(Color.blue); 
  g2.fillRect(125,75,100,100); 
  g2.setColor(Color.yellow); 
  g2.fillRect(50,125,100,100); 
  g2.setColor(Color.pink); 
  g2.fillRect(-25,75,100,100); 
} 

2.4 グラフィックスプリミティブのレンダリング

Graphics2D では、ShapesText、および Images のレンダリング用に、次のメソッドが提供されています。

図形を描画して塗りつぶすには、draw メソッドと fill メソッドの両方を呼び出す必要があります。

Graphics2D は、drawOvalfillRect など、旧バージョンの JDK で提供されていた描画用と塗りつぶし用のメソッドもサポートしています。

2.4.1 図形の描画

Shape の輪郭線は、Graphics2D.draw メソッドでレンダリングできます。旧バージョンの JDK で提供されていた次の描画メソッドもサポートされています。drawLinedrawRectdrawRoundRectdrawOvaldrawArcdrawPolylinedrawPolygondraw3DRect

Shape を描画すると、Graphics2D コンテキストの Stroke オブジェクトでパスが描画されます。詳細については、「ストローク属性」を参照してください。Graphics2D コンテキストに適切な BasicStroke オブジェクトを設定することで、どのような幅とパターンの線でも描画できます。BasicStroke オブジェクトでは、線の先端部と接合部の属性も定義されています。

図形の輪郭線は、次の手順でレンダリングします。

次の例では、GeneralPath オブジェクトを使って星型を定義し、BasicStroke オブジェクトを Graphics2D コンテキストに追加して、星型の輪郭線の幅と接合部の属性を定義しています。

public void paint(Graphics g) { 
  Graphics2D g2 = (Graphics2D) g; 
 
  // create and set the stroke 
  g2.setStroke(new BasicStroke(4.0f)); 
 
  // Create a star using a general path object 
  GeneralPath p = new GeneralPath(GeneralPath.NON_ZERO); 
  p.moveTo(- 100.0f, - 25.0f); 
  p.lineTo(+ 100.0f, - 25.0f); 
  p.lineTo(- 50.0f, + 100.0f); 
  p.lineTo(+ 0.0f, - 100.0f); 
  p.lineTo(+ 50.0f, + 100.0f); 
  p.closePath(); 
 
  // translate origin towards center of canvas 
  g2.translate(100.0f, 100.0f); 
  
  // render the star's path 
  g2.draw(p); 
} 

2.4.2 図形の塗りつぶし

Graphics2D.fill メソッドを使って、任意の Shape塗りつぶすことができます。Shape を塗りつぶすと、そのパスの内側の領域が、ColorTexturePaintGradientPaint など、Graphics2D コンテキストの現在の Paint 属性でレンダリングされます。

旧バージョンの JDK で提供されていた次の塗りつぶしメソッドもサポートされています。fillRectfill3DRectfillRoundRectfillOvalfillArcfillPolygonclearRect

Shape の塗りつぶしは、次の手順で行います。

次の例では、setColor を呼び出し、緑色での塗りつぶしを Rectangle2D に定義しています。

public void paint(Graphics g) { 
  Graphics2D g2 = (Graphics2D) g; 
 
  g2.setPaint(Color.green); 
  Rectangle2D r2 = new Rectangle2D.Float(25,25,150,150); 
 
   g2.fill(r2); 
} 

2.4.3 テキストのレンダリング

テキスト文字列をレンダリングするには、Graphics2D.drawString を呼び出して、レンダリングする文字列を渡します。テキストのレンダリングとフォントの選択についての詳細は、「フォントとテキストレイアウト」を参照してください。

2.4.4 イメージのレンダリング

Image をレンダリングするには、Image を作成し、Graphics2D.drawImage を呼び出します。イメージの処理とレンダリングの詳細については、「イメージング」を参照してください。

2.5 独自の合成規則の定義

Composite インタフェースと CompositeContext インタフェースを実装することで、まったく新しい種類の合成操作を作成できます。Composite オブジェクトでは、実際に状態を保持して合成の作業を行う CompositeContext オブジェクトが提供されます。1 つの Composite オブジェクトから複数の CompositeContext オブジェクトを生成し、マルチスレッド環境の異なる状態を維持できます。

2.6 マルチスクリーン環境でのレンダリング

JavaTM 2 SDK のバージョン 1.3 以降のリリースにより、Java 2DTM API は、ネイティブプラットフォームで構成可能な 3 つの異なるマルチスクリーン構成をサポートします。

Java 2D API を利用することにより、GraphicsConfiguration を使って FrameJFrameWindow、または JWindow オブジェクトを作成し、レンダリング用の画面デバイスをターゲットにできます。

これら 3 つの構成で、各画面デバイスは GraphicsDevice で表されます。GraphicsDevice は、関連付けられた複数の GraphicsConfiguration オブジェクトを保持できます。

仮想デバイスの構成に複数の画面が使用される場合、物理画面外に存在する仮想座標系が、仮想デバイスの表現に使用されます。マルチスクリーン構成での各 GraphicsConfiguration の境界は、仮想座標系に対する相対座標になります。この環境下で 1 つの画面がプライマリ画面として認識され、仮想座標系の (0, 0) に配置されます。図 2-10 に示すように、プライマリ画面の位置によっては、仮想デバイスが負の座標になる場合があります。

仮想デバイス、物理画面、フレームまたはウィンドウ、およびプライマリ物理画面を示す仮想デバイス環境の例
図 2-10 仮想デバイス環境の例

Window または Frame が複数の物理画面にまたがる現在の環境が仮想デバイス環境であるかどうかを判別するには、システムの GraphicsConfiguration ごとに getBounds を呼び出して、原点が (0, 0) 以外に位置しているかどうかを調べます。GraphicsConfigurationgetBounds メソッドは、仮想座標系内の Rectangle を返します。このため、原点が (0, 0) 以外の場合には、仮想デバイス環境です。

仮想デバイス環境では、GraphicsConfiguration オブジェクトの座標は仮想座標系に対する相対座標になります。このため、Frame または WindowsetLocation メソッドを呼び出す場合には、仮想座標を使用する必要があります。たとえば次のコード例では、GraphicsConfiguration の境界を取得し、その境界を使って、対応する GraphicsConfiguration の物理画面の原点に対し (10, 10) の位置に Frame を配置します。

Frame f = new Frame(GraphicsConfiguration gc); 
Rectangle bounds = gc.getBounds(); 
f.setLocation(10 + bounds.x, 10 + bounds.y); 
 

GraphicsConfiguration の境界が考慮されていない場合、Frame はプライマリの物理画面の (10, 10) に表示されます。この位置は、指定された GraphicsConfiguration の物理画面とは異なる場合があります。

仮想デバイスの境界判定に、getBounds メソッドを使用することもできます。システムの各 GraphicsConfiguration に対し、getBounds を呼び出します。仮想デバイスの境界を決定するには、すべての境界の和集合を計算します。次の例では、その具体的な方法を示します。

Rectangle virtualBounds = new Rectangle(); 
GraphicsEnvironment ge = 
   GraphicsEnvironment.getLocalGraphicsEnvironment(); 
GraphicsDevice[] gs = ge.getScreenDevices(); 
for (int j = 0; j < gs.length; j++) { 
   GraphicsDevice gd = gs[j]; 
   GraphicsConfiguration[] gc = gd.getConfigurations(); 
   for (int i = 0; i < gc.length; i++) { 
      virtualBounds = virtualBounds.union(gc[i].getBounds()); 
   } 
} 
 

次のアプレットは、GraphicsEnvironment の各 GraphicsDeviceGraphicsConfiguration を使って JFrame を作成します。各 JFrame は、赤、緑、青のストライプセット、画面番号、GraphicsConfiguration 番号、および GraphicsConfiguration の境界を表示します。


import java.applet.Applet; 
import java.awt.*; 
import javax.swing.*; 
 
public class MultiFrameApplet extends Applet { 
    
    public MultiFrameApplet() { 
        main(null); 
    } 
 
    public static void main(String[] argv) { 
        GraphicsEnvironment ge = 
           GraphicsEnvironment.getLocalGraphicsEnvironment(); 
        GraphicsDevice[] gs = ge.getScreenDevices(); 
        for (int j = 0; j < gs.length; j++) { 
          GraphicsDevice gd = gs[j]; 
          GraphicsConfiguration[] gc = 
             gd.getConfigurations(); 
             for (int i=0; i < gc.length; i++) { 
               JFrame f = 
                  new JFrame(gs[j].getDefaultConfiguration()); 
               GCCanvas c = new GCCanvas(gc[i]); 
               Rectangle gcBounds = gc[i].getBounds(); 
               int xoffs = gcBounds.x; 
               int yoffs = gcBounds.y; 
               f.getContentPane().add(c); 
               f.setTitle("Screen# "+Integer.toString(j)+", 
                  GC# "+Integer.toString(i)); 
               f.setSize(300, 150); 
               f.setLocation((i*50)+xoffs, (i*60)+yoffs); 
               f.show(); 
             } 
        } 
    } 
} 
 
class GCCanvas extends Canvas { 
 
    GraphicsConfiguration gc; 
    Rectangle bounds; 
 
    public GCCanvas(GraphicsConfiguration gc) { 
        super(gc); 
        this.gc = gc; 
        bounds = gc.getBounds(); 
    } 
 
    public Dimension getPreferredSize() { 
        return new Dimension(300, 150); 
    } 
 
    public void paint(Graphics g) { 
        g.setColor(Color.red); 
        g.fillRect(0, 0, 100, 150); 
        g.setColor(Color.green); 
        g.fillRect(100, 0, 100, 150); 
        g.setColor(Color.blue); 
        g.fillRect(200, 0, 100, 150); 
        g.setColor(Color.black); 
        g.drawString("ScreenSize="+ 
           Integer.toString(bounds.width)+ 
           "X"+ Integer.toString(bounds.height), 10, 15); 
        g.drawString(gc.toString(), 10, 30); 
    } 
} 
 

 


目次 | 前へ | 次へ

Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.