JavaTM 2 Platform
Standard Ed. 6

java.awt.font
类 LineBreakMeasurer

java.lang.Object
  继承者 java.awt.font.LineBreakMeasurer

public final class LineBreakMeasurer
extends Object

LineBreakMeasurer 类允许将样式化的文本断为行(或段),以符合特定的可视 advance。这对希望显示适合指定宽度(称为环绕宽度)文本段落的客户端很有用。

LineBreakMeasurer 通过样式化文本上的迭代器构造。该迭代器的范围应该是文本中的单个段落。LineBreakMeasurer 保存文本中用于开始下一个文本段的位置。最初,此位置是文本的开始点。根据双向格式规则,为段落分配了总体方向(从左到右或从右到左)。从段落获得的所有段具有与该段落相同的方向。

通过调用方法 nextLayout 可获得文本的段,该方法会返回表示符合该环绕宽度的文本的 TextLayoutnextLayout 方法将当前位置移动到从 nextLayout 返回的布局末尾。

LineBreakMeasurer 实现最常用的换行策略:在该行上放置符合环绕宽度的每一个词。如果第一个词不符合,那么适合环绕宽度的所有字符将放置在该行上。每行至少放置一个字符。

LineBreakMeasurer 返回的 TextLayout 实例将 TAB 视为 0 宽度的空格。为了定位而希望获得以 TAB 分界的段的客户端应该重载 nextLayout,它可以在文本实行限制偏移量。限制偏移量应该是 TAB 后的第一个字符。从此方法返回的 TextLayout 对象在提供的界限处(或者界限之前,条件是当前位置和该界限之间的文本没有完全位于环绕宽度之内)结束。

在行上放置首段之后,正在布局 TAB 分隔文本的客户端需要稍微不同的换行策略。新策略不是将部分词放入剩余空间,而是应该将无法完全放入剩余空间的词放在下一行。带有 boolean 参数的 nextLayout 重载中可能请求这种策略更改。如果此参数为 true,且第一个词无法放入给定的空间,则 nextLayout 返回 null。请参见下面的 TAB 示例。

通常,如果用于构造 LineBreakMeasurer 的文本发生更改,则必须构造新的 LineBreakMeasurer 以反映此更改。(原来的 LineBreakMeasurer 可继续正常工作,但文本的更改对于它是未知的。)但是如果该文本更改是插入或删除单个字符,则可通过调用 insertChardeleteChar 来“更新”现有的 LineBreakMeasurer。更新现有的 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();
     }
 }
 

使用 TAB 呈现文本。为简单起见,假定总体的文本方向为从左到右

 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)
          从文本删除单个字符之后,更新此 LineBreakMeasurer,并将当前位置设置为段落的开始。
 int getPosition()
          返回此 LineBreakMeasurer 的当前位置。
 void insertChar(AttributedCharacterIterator newParagraph, int insertPos)
          将单个字符插入文本后,更新此 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 - 此 LineBreakMeasurer 为其生成 TextLayout 对象的文本;该文本必须至少包含一个字符;如果通过 iter 提供的文本发生更改,则再次调用此 LineBreakMeasurer 实例是不明确的(后来调用 insertChardeleteChar 等某些情况除外 - 参见下面内容)
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 对象的文本;该文本必须至少包含一个字符;如果通过 iter 提供的文本发生更改,则再次调用此 LineBreakMeasurer 实例是不明确的(后来调用 insertChardeleteChar 等某些情况除外 - 参见下面内容)
breakIter - 定义换行的 BreakIterator
frc - 包含关于正确测量文本所需的图形设备的信息;由于设备分辨率和属性(抗锯齿)的不同,文本测量可能稍有变化;此参数不指定 LineBreakMeasurer 和用户空间之间的转换
抛出:
IllegalArgumentException - 如果文本少于一个字符
另请参见:
insertChar(java.text.AttributedCharacterIterator, int), deleteChar(java.text.AttributedCharacterIterator, int)
方法详细信息

nextOffset

public int nextOffset(float wrappingWidth)
返回下一个布局结尾处的位置。不更新此 LineBreakMeasurer 的当前位置。

参数:
wrappingWidth - 下一布局中文本所允许的最大可视 advance
返回:
文本中表示下一个 TextLayout 限制的偏移量。

nextOffset

public int nextOffset(float wrappingWidth,
                      int offsetLimit,
                      boolean requireNextWord)
返回下一个布局结尾处的位置。不更新此 LineBreakMeasurer 的当前位置。

参数:
wrappingWidth - 下一布局中文本所允许的最大可视 advance
offsetLimit - 即使限制后的文本适合该环绕宽度,下一个布局中也无法包括的第一个字符;offsetLimit 必须大于当前位置
requireNextWord - 如果为 true,且下一个词的全部不适合 wrappingWidth,则为返回的当前位置;如果为 false,则返回的偏移量至少比当前位置大一
返回:
文本中表示下一个 TextLayout 限制的偏移量。

nextLayout

public TextLayout nextLayout(float wrappingWidth)
返回下一个布局,并更新当前位置。

参数:
wrappingWidth - 下一布局中文本所允许的最大可视 advance
返回:
从当前位置开始的 TextLayout,它表示适合 wrappingWidth 的下一行。

nextLayout

public TextLayout nextLayout(float wrappingWidth,
                             int offsetLimit,
                             boolean requireNextWord)
返回下一个布局,并更新当前位置。

参数:
wrappingWidth - 下一个布局中文本所允许的最大可视 advance
offsetLimit - 即使限制后的文本适合环绕宽度,下一个布局中也无法包括的第一个字符;offsetLimit 必须大于当前位置
requireNextWord - 如果为 true,并且当前位置的整个词不适合环绕宽度,则返回 null。如果为 false,则返回有效的布局,该布局至少包括当前位置的字符
返回:
从当前位置开始的 TextLayout,它表示适合 wrappingWidth 的下一行。如果当前位置位于由此 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)
将单个字符插入文本后,更新此 LineBreakMeasurer,并将当前位置设置为段落的开始。

参数:
newParagraph - 插入后的文本
insertPos - 文本中插入字符的位置
抛出:
IndexOutOfBoundsException - 如果 insertPos 小于 newParagraph 的开始,或者大于或等于 newParagraph 的末尾
NullPointerException - 如果 newParagraphnull
另请参见:
deleteChar(java.text.AttributedCharacterIterator, int)

deleteChar

public void deleteChar(AttributedCharacterIterator newParagraph,
                       int deletePos)
从文本删除单个字符之后,更新此 LineBreakMeasurer,并将当前位置设置为段落的开始。

参数:
newParagraph - 删除之后的文本
deletePos - 文本中删除字符的位置
抛出:
IndexOutOfBoundsException - 如果 deletePos 小于 newParagraph 的开始,或大于 newParagraph 的末尾
NullPointerException - 如果 newParagraphnull
另请参见:
insertChar(java.text.AttributedCharacterIterator, int)

JavaTM 2 Platform
Standard Ed. 6

提交错误或意见

版权所有 2008 Sun Microsystems, Inc. 保留所有权利。请遵守GNU General Public License, version 2 only