目次||

第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になります。唯一の違いは、Java 2D APIはレンダリングの前に、テキストに適用されるFontを判別し、Fontから適切なグリフを取得する必要があることです。

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

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

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

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

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

アンチエイリアス

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

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

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

2.2.3 ストローク属性

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

Graphics2Dコンテキストのストローク属性を定義するには、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インタフェースのもっとも簡単な実装です。

グラデーションやテクスチャのようなさらに複雑な描画スタイルでShapeを塗りつぶすには、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という変換クラスが提供されています。AffineTransformを使用して、レンダリングの際のテキスト、図形およびイメージの変換が行われます。Fontオブジェクトに変換を適用し、新しいフォント派生を作成することもできます。詳細については、「フォント派生の作成」を参照してください。

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

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

 

先頭行にa、cおよびtサブxを含む2x3の行列。2行目にはb、d、およびtサブyを含んでいます。ここでは、xプライムイコールaxプラスcyプラスtサブxおよびyプライムイコールbxプラスdyプラスtサブyです

 

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

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

2.2.6.1 AffineTransformの構築

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

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

2.2.7 合成属性

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

Java 2Dの合成処理モデルの基礎になるインタフェースは、CompositeCompositeContextの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 ソースが上

2.2.7.1 透明度の管理

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

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

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

2.2.7.2 透明度とイメージ

イメージには、イメージ内の各ピクセルに対する透明度の情報を持たせることができます。アルファ・チャネルと呼ばれるこの情報は、イメージと既存の描画結果を混合するために、Graphics2Dコンテキストのe 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にそれを渡します。

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

次の例では、アンチエイリアスを有効にし、レンダリングの設定を品質優先にしています。

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属性により、テキストとShapeのレンダリング時に使われる塗りつぶしの色とパターンが決まります。

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では、ShapeTextおよびImageのレンダリング用に、次のメソッドが提供されています。

図形をストロークで描画して塗りつぶすには、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 マルチスクリーン環境でのレンダリング

Java 2D 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の各GraphicsDeviceの各GraphicsConfigurationを使用して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, 2020, Oracle and/or its affiliates. All rights reserved.