- java.lang.Object
-
- java.awt.font.LineBreakMeasurer
-
public final class LineBreakMeasurer extends Object
LineBreakMeasurer
クラスを使用すれば、書式付きテキストを、特定の可視有効幅に収まる行(またはセグメント)に分けることができます。 これは、固有の幅(ラッピング幅と呼ばれます)に収まるテキストの段落をクライアントに表示する場合に便利です。LineBreakMeasurer
は、書式付きテキストに対するイテレータを使って構築されます。 イテレータの範囲はテキスト内の1つの段落です。LineBreakMeasurer
は、次のテキスト・セグメントを開始するための、テキスト内の位置を保持します。 最初は、この位置がテキストの始点です。 段落の方向は、双方向フォーマット規則に従って、全方向(左から右または右から左)に及びます。 段落から取得されたすべてのセグメントは、その段落と同じ方向になります。テキストのセグメントは、
nextLayout
メソッドを呼び出すことで取得されます。このメソッドは、ラッピング幅に収まるテキストを表すTextLayout
を返します。nextLayout
メソッドは、nextLayout
が返したレイアウトの終端に現在の位置を移動します。LineBreakMeasurer
は、もっとも一般的に使用される次のような改行ポリシーを実装します。ラッピング幅に収まるすべての単語は、同じ行に配置されます。 最初の単語が収まらなければ、ラッピング幅に収まるだけの文字がその行に配置されます。 各行には少なくとも1文字が配置されます。LineBreakMeasurer
によって返されるTextLayout
のインスタンスは、タブを幅0のスペースと同様に扱います。 位置決めのためにタブ区切りのセグメントを取得するクライアントは、テキストに対するリミット・オフセットをとるnextLayout
のオーバーロードを使うようにしてください。 リミット・オフセットは、タブ以降の最初の文字です。 このメソッドが返すTextLayout
オブジェクトは、指定されたリミット(現在の位置とリミットとの間のテキスト全体がラッピング幅に収まらない場合には、リミットの前)で終わります。タブ区切りのテキストをレイアウトするクライアントには、最初のセグメントを行に配置したあと、やや異なる改行ポリシーが必要です。 残りの領域に一部の単語を収めるのではなく、全体を次の行に配置します。 ポリシーのこの変更は、
boolean
パラメータをとるnextLayout
のオーバーロードで要求できます。 このパラメータがtrue
の場合、nextLayout
は、最初の単語が指定された領域に収まらないときにnull
を返します。 下記のタブ・サンプルを参照してください。通常、
LineBreakMeasurer
の作成に使用されたテキストが変更された場合は、変更を反映するために新しいLineBreakMeasurer
を作成する必要があります。 (これまでのLineBreakMeasurer
はそのまま正常に動作するが、テキストの変更には対応しない。) ただし、テキストの変更が1文字の挿入または削除の場合には、insertChar
またはdeleteChar
を呼び出して、既存のLineBreakMeasurer
を「更新」してもかまいません。 既存のLineBreakMeasurer
を更新する方が、新しく作成するよりも処理時間がかかりません。 ユーザーのキー入力によってテキストを変更する場合は、これらの方法を利用するとよいでしょう。例:
コンポーネントに段落を描画します。
public void paint(Graphics graphics) { float dx = 0f, dy = 5f; Graphics2D g2d = (Graphics2D)graphics; FontRenderContext frc = g2d.getFontRenderContext(); AttributedString text = new AttributedString("....."); AttributedCharacterIterator paragraph = text.getIterator(); LineBreakMeasurer measurer = new LineBreakMeasurer(paragraph, frc); measurer.setPosition(paragraph.getBeginIndex()); float wrappingWidth = (float)getSize().width; while (measurer.getPosition() < paragraph.getEndIndex()) { TextLayout layout = measurer.nextLayout(wrappingWidth); dy += (layout.getAscent()); float dx = layout.isLeftToRight() ? 0 : (wrappingWidth - layout.getAdvance()); layout.draw(graphics, dx, dy); dy += layout.getDescent() + layout.getLeading(); } }
タブ付きのテキストを描画します。 わかりやすくするため、テキストの方向はすべて左から右とします。
public void paint(Graphics graphics) { float leftMargin = 10, rightMargin = 310; float[] tabStops = { 100, 250 }; // assume styledText is an AttributedCharacterIterator, and the number // of tabs in styledText is tabCount int[] tabLocations = new int[tabCount+1]; int i = 0; for (char c = styledText.first(); c != styledText.DONE; c = styledText.next()) { if (c == '\t') { tabLocations[i++] = styledText.getIndex(); } } tabLocations[tabCount] = styledText.getEndIndex() - 1; // Now tabLocations has an entry for every tab's offset in // the text. For convenience, the last entry is tabLocations // is the offset of the last character in the text. LineBreakMeasurer measurer = new LineBreakMeasurer(styledText); int currentTab = 0; float verticalPos = 20; while (measurer.getPosition() < styledText.getEndIndex()) { // Lay out and draw each line. All segments on a line // must be computed before any drawing can occur, since // we must know the largest ascent on the line. // TextLayouts are computed and stored in a Vector; // their horizontal positions are stored in a parallel // Vector. // lineContainsText is true after first segment is drawn boolean lineContainsText = false; boolean lineComplete = false; float maxAscent = 0, maxDescent = 0; float horizontalPos = leftMargin; Vector layouts = new Vector(1); Vector penPositions = new Vector(1); while (!lineComplete) { float wrappingWidth = rightMargin - horizontalPos; TextLayout layout = measurer.nextLayout(wrappingWidth, tabLocations[currentTab]+1, lineContainsText); // layout can be null if lineContainsText is true if (layout != null) { layouts.addElement(layout); penPositions.addElement(new Float(horizontalPos)); horizontalPos += layout.getAdvance(); maxAscent = Math.max(maxAscent, layout.getAscent()); maxDescent = Math.max(maxDescent, layout.getDescent() + layout.getLeading()); } else { lineComplete = true; } lineContainsText = true; if (measurer.getPosition() == tabLocations[currentTab]+1) { currentTab++; } if (measurer.getPosition() == styledText.getEndIndex()) lineComplete = true; else if (horizontalPos >= tabStops[tabStops.length-1]) lineComplete = true; if (!lineComplete) { // move to next tab stop int j; for (j=0; horizontalPos >= tabStops[j]; j++) {} horizontalPos = tabStops[j]; } } verticalPos += maxAscent; Enumeration layoutEnum = layouts.elements(); Enumeration positionEnum = penPositions.elements(); // now iterate through layouts and draw them while (layoutEnum.hasMoreElements()) { TextLayout nextLayout = (TextLayout) layoutEnum.nextElement(); Float nextPosition = (Float) positionEnum.nextElement(); nextLayout.draw(graphics, nextPosition.floatValue(), verticalPos); } verticalPos += maxDescent; } }
- 関連項目:
TextLayout
-
-
コンストラクタのサマリー
コンストラクタ コンストラクタ 説明 LineBreakMeasurer(AttributedCharacterIterator text, FontRenderContext frc)
指定されたテキストに対するLineBreakMeasurer
を構築します。LineBreakMeasurer(AttributedCharacterIterator text, BreakIterator breakIter, FontRenderContext frc)
指定されたテキストに対するLineBreakMeasurer
を構築します。
-
メソッドのサマリー
すべてのメソッド インスタンス・メソッド 具象メソッド 修飾子と型 メソッド 説明 void
deleteChar(AttributedCharacterIterator newParagraph, int deletePos)
テキストから文字が1つ削除されたあとにLineBreakMeasurer
を更新して、現在の位置をその段落の先頭に設定します。int
getPosition()
このLineBreakMeasurer
の現在の位置を返します。void
insertChar(AttributedCharacterIterator newParagraph, int insertPos)
テキストに文字が1つ挿入されたあとにLineBreakMeasurer
を更新して、現在の位置をその段落の先頭に設定します。TextLayout
nextLayout(float wrappingWidth)
次のレイアウトを返し、現在の位置を更新します。TextLayout
nextLayout(float wrappingWidth, int offsetLimit, boolean requireNextWord)
次のレイアウトを返し、現在の位置を更新します。int
nextOffset(float wrappingWidth)
次のレイアウトの最後の位置を返します。int
nextOffset(float wrappingWidth, int offsetLimit, boolean requireNextWord)
次のレイアウトの最後の位置を返します。void
setPosition(int newPosition)
LineBreakMeasurer
の現在の位置を設定します。
-
-
-
コンストラクタの詳細
-
LineBreakMeasurer
public LineBreakMeasurer(AttributedCharacterIterator text, FontRenderContext frc)
指定されたテキストに対するLineBreakMeasurer
を構築します。- パラメータ:
text
- このLineBreakMeasurer
がTextLayout
オブジェクトの生成対象とするテキスト。このテキストには、1つ以上の文字が含まれていなければならない。iter
で得られるテキストが変更された場合、その後のこのLineBreakMeasurer
のインスタンスへの呼出しの結果は保証されない(ただし、あとでinsertChar
またはdeleteChar
を呼び出す場合を除く。関連項目を参照)frc
- テキストを正確に測定するために必要なグラフィックス・デバイスに関する情報を格納する。テキスト測定は、デバイスの解像度によりわずかに異なり、アンチエイリアスなどの属性によっても異なる。このパラメータは、LineBreakMeasurer
とユーザー空間の間の変換は指定しない。- 関連項目:
insertChar(java.text.AttributedCharacterIterator, int)
,deleteChar(java.text.AttributedCharacterIterator, int)
-
LineBreakMeasurer
public LineBreakMeasurer(AttributedCharacterIterator text, BreakIterator breakIter, FontRenderContext frc)
指定されたテキストに対するLineBreakMeasurer
を構築します。- パラメータ:
text
- このLineBreakMeasurer
がTextLayout
オブジェクトの生成対象とするテキスト。このテキストには、1つ以上の文字が含まれていなければならない。iter
で得られるテキストが変更された場合、その後のこのLineBreakMeasurer
のインスタンスへの呼出しの結果は保証されない(ただし、あとでinsertChar
またはdeleteChar
を呼び出す場合を除く。関連項目を参照)breakIter
- 改行を定義するBreakIterator
frc
- テキストを正確に測定するために必要なグラフィックス・デバイスに関する情報を格納する。テキスト測定は、デバイスの解像度によりわずかに異なり、アンチエイリアスなどの属性によっても異なる。このパラメータは、LineBreakMeasurer
とユーザー空間の間の変換は指定しない。- 例外:
IllegalArgumentException
- テキストが1文字に満たない場合- 関連項目:
insertChar(java.text.AttributedCharacterIterator, int)
,deleteChar(java.text.AttributedCharacterIterator, int)
-
-
メソッドの詳細
-
nextOffset
public int nextOffset(float wrappingWidth)
次のレイアウトの最後の位置を返します。LineBreakMeasurer
の現在の位置を更新しません。- パラメータ:
wrappingWidth
- 次のレイアウト内のテキストに許容される最大の可視有効幅- 戻り値:
- 次の
TextLayout
のリミットを表す、テキスト内のオフセット。
-
nextOffset
public int nextOffset(float wrappingWidth, int offsetLimit, boolean requireNextWord)
次のレイアウトの最後の位置を返します。LineBreakMeasurer
の現在の位置を更新しません。- パラメータ:
wrappingWidth
- 次のレイアウト内のテキストに許容される最大の可視有効幅offsetLimit
- リミット以降のテキストがラッピング幅に収まる場合でも、次のレイアウトに含まれない最初の文字。offsetLimit
は、現在の位置よりも大きくなければならない。requireNextWord
-true
の場合、次の単語全体がwrappingWidth
に収まらないときは現在の位置が返される。false
の場合、返されるオフセットは現在の位置よりも少なくとも1大きい- 戻り値:
- 次の
TextLayout
のリミットを表す、テキスト内のオフセット
-
nextLayout
public TextLayout nextLayout(float wrappingWidth)
次のレイアウトを返し、現在の位置を更新します。- パラメータ:
wrappingWidth
- 次のレイアウト内のテキストに許容される最大の可視有効幅- 戻り値:
wrappingWidth
に収まる次の行を表し、現在の位置から始まるTextLayout
-
nextLayout
public TextLayout nextLayout(float wrappingWidth, int offsetLimit, boolean requireNextWord)
次のレイアウトを返し、現在の位置を更新します。- パラメータ:
wrappingWidth
- 次のレイアウト内のテキストに許容される最大の可視有効幅offsetLimit
- リミット以降のテキストがラッピング幅に収まる場合でも、次のレイアウトに含まれない最初の文字。offsetLimit
は、現在の位置よりも大きくなければならない。requireNextWord
-true
の場合、現在の位置にある単語全体がラッピング幅に収まらないときはnull
が返される。false
の場合、少なくとも現在の位置にある文字を含む、有効なレイアウトが返される- 戻り値:
wrappingWidth
に収まる次の行を表し、現在の位置から始まるTextLayout
。 現在の位置が、このLineBreakMeasurer
の使用するテキストの終端にある場合、null
が返される
-
getPosition
public int getPosition()
このLineBreakMeasurer
の現在の位置を返します。- 戻り値:
- この
LineBreakMeasurer
の現在の位置 - 関連項目:
setPosition(int)
-
setPosition
public void setPosition(int newPosition)
LineBreakMeasurer
の現在の位置を設定します。- パラメータ:
newPosition
- このLineBreakMeasurer
の現在の位置。この位置は、このLineBreakMeasurer
を作成するために使用されるテキスト(またはinsertChar
かdeleteChar
に最後に渡されたテキスト)内にある- 関連項目:
getPosition()
-
insertChar
public void insertChar(AttributedCharacterIterator newParagraph, int insertPos)
テキストに文字が1つ挿入されたあとにLineBreakMeasurer
を更新して、現在の位置をその段落の先頭に設定します。- パラメータ:
newParagraph
- 挿入後のテキストinsertPos
- テキスト内の、文字が挿入された位置- 例外:
IndexOutOfBoundsException
-insertPos
がnewParagraph
の開始位置より前、またはnewParagraph
の終了位置と同じか、それより後ろである場合NullPointerException
-newParagraph
がnull
である場合- 関連項目:
deleteChar(java.text.AttributedCharacterIterator, int)
-
deleteChar
public void deleteChar(AttributedCharacterIterator newParagraph, int deletePos)
テキストから文字が1つ削除されたあとにLineBreakMeasurer
を更新して、現在の位置をその段落の先頭に設定します。- パラメータ:
newParagraph
- 削除後のテキストdeletePos
- テキスト内の、文字が削除された位置- 例外:
IndexOutOfBoundsException
-deletePos
がnewParagraph
の開始位置より前、またはnewParagraph
の終了位置より後ろである場合NullPointerException
-newParagraph
がnull
である場合- 関連項目:
insertChar(java.text.AttributedCharacterIterator, int)
-
-