JavaTM Platform
Standard Ed. 6

java.awt.font
クラス LineBreakMeasurer

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) {

     Point2D pen = new Point2D(10, 20);
     Graphics2D g2d = (Graphics2D)graphics;
     FontRenderContext frc = g2d.getFontRenderContext();

     // let styledText be an AttributedCharacterIterator containing at least
     // one character

     LineBreakMeasurer measurer = new LineBreakMeasurer(styledText, frc);
     float wrappingWidth = getSize().width - 15;

     while (measurer.getPosition() < fStyledText.length()) {

         TextLayout layout = measurer.nextLayout(wrappingWidth);

         pen.y += (layout.getAscent());
         float dx = layout.isLeftToRight() ?
             0 : (wrappingWidth - layout.getAdvance());

         layout.draw(graphics, pen.x + dx, pen.y);
         pen.y += 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, BreakIterator breakIter, FontRenderContext frc)
          指定されたテキストに対する LineBreakMeasurer を構築します。
LineBreakMeasurer(AttributedCharacterIterator text, 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 の現在の位置を設定します。
 
クラス java.lang.Object から継承されたメソッド
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

コンストラクタの詳細

LineBreakMeasurer

public LineBreakMeasurer(AttributedCharacterIterator text,
                         FontRenderContext frc)
指定されたテキストに対する LineBreakMeasurer を構築します。

パラメータ:
text - この LineBreakMeasurerTextLayout オブジェクトの生成対象とするテキスト。 このテキストには、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 - この LineBreakMeasurerTextLayout オブジェクトの生成対象とするテキスト。 このテキストには、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 を作成するために使用されるテキスト (または insertChardeleteChar に最後に渡されたテキスト) 内にある
関連項目:
getPosition()

insertChar

public void insertChar(AttributedCharacterIterator newParagraph,
                       int insertPos)
テキストに文字が 1 つ挿入されたあとに LineBreakMeasurer を更新して、現在の位置をその段落の先頭に設定します。

パラメータ:
newParagraph - 挿入後のテキスト
insertPos - テキスト内の、 文字が挿入された位置
例外:
IndexOutOfBoundsException - insertPosnewParagraph の開始位置より前、 または newParagraph の終了位置と同じか、それ以降である場合
NullPointerException - newParagraphnull の場合
関連項目:
deleteChar(java.text.AttributedCharacterIterator, int)

deleteChar

public void deleteChar(AttributedCharacterIterator newParagraph,
                       int deletePos)
テキストから文字が 1 つ削除されたあとに LineBreakMeasurer を更新して、現在の位置をその段落の先頭に設定します。

パラメータ:
newParagraph - 削除後のテキスト
deletePos - テキスト内の、 文字が削除された位置
例外:
IndexOutOfBoundsException - deletePosnewParagraph の開始位置より前、 または newParagraph の終了位置より後ろである場合
NullPointerException - newParagraphnull の場合
関連項目:
insertChar(java.text.AttributedCharacterIterator, int)

JavaTM Platform
Standard Ed. 6

バグの報告と機能のリクエスト
さらに詳しい API リファレンスおよび開発者ドキュメントについては、Java SE 開発者用ドキュメントを参照してください。開発者向けの詳細な解説、概念の概要、用語の定義、バグの回避策、およびコード実例が含まれています。

Copyright 2006 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. Documentation Redistribution Policy も参照してください。