TextLayout是样式化字符数据的不可变图形表示。
它提供以下功能:
隐式双向分析和重新排序,
光标定位和移动,包括用于混合方向文本的分割光标,
突出显示,包括混合方向文本的逻辑和视觉突出显示,
多个基线(罗马,悬挂和居中),
打击测试,
理由,
默认字体替换,
度量信息,如上升,下降和前进,以及
翻译
可以使用其draw方法呈现TextLayout对象。
TextLayout可以直接构建,也可以使用LineBreakMeasurer构建 。 直接构造时,源文本代表单个段落。 LineBreakMeasurer允许将样式化文本拆分为适合特定宽度的行。 有关更多信息,请参见LineBreakMeasurer文档。
TextLayout建设逻辑上如下:
段落属性被提取和检查,
分析文本以进行双向重新排序,并在需要时计算重新排序信息,
文本被分段为样式运行
为样式运行选择字体,如果存在属性TextAttribute.FONT则首先使用字体,否则通过使用已定义的属性计算默认字体
如果文本在多个基线上,则运行或子运行进一步分解为共享共同基线的子运行,
使用所选字体为每次运行生成glyphvectors,
对glyphvectors执行最终双向重新排序
从TextLayout对象的方法返回的所有图形信息都是相对于TextLayout的原点,它是TextLayout对象的基线与其左边缘的交点。 此外,传递到TextLayout对象的方法的坐标被假定为相对于TextLayout对象的原点。 客户端通常需要在TextLayout对象的坐标系和另一个对象(例如Graphics对象)中的坐标系之间进行转换。
TextLayout对象是从样式文本构造的,但它们不保留对其源文本的引用。 因此,先前用于生成TextLayout的文本中的更改不会影响TextLayout 。
一对三种方法TextLayout对象( getNextRightHit , getNextLeftHit和hitTestChar )返回的实例TextHitInfo 。 这些TextHitInfo对象中包含的偏移量相对于TextLayout , 而不是用于创建TextLayout的文本。 类似地,接受TextHitInfo实例作为参数的TextLayout方法期望TextHitInfo对象的偏移量相对于TextLayout ,而不是任何基础文本存储模型。
示例 :
构造和绘制TextLayout及其边界矩形:
Graphics2D g = ...;
Point2D loc = ...;
Font font = Font.getFont("Helvetica-bold-italic");
FontRenderContext frc = g.getFontRenderContext();
TextLayout layout = new TextLayout("This is a string", font, frc);
layout.draw(g, (float)loc.getX(), (float)loc.getY());
Rectangle2D bounds = layout.getBounds();
bounds.setRect(bounds.getX()+loc.getX(),
bounds.getY()+loc.getY(),
bounds.getWidth(),
bounds.getHeight());
g.draw(bounds);
点击测试TextLayout (确定哪个角色位于特定的图形位置):
Point2D click = ...;
TextHitInfo hit = layout.hitTestChar(
(float) (click.getX() - loc.getX()),
(float) (click.getY() - loc.getY()));
响应右箭头键按:
int insertionIndex = ...;
TextHitInfo next = layout.getNextRightHit(insertionIndex);
if (next != null) {
// translate graphics to origin of layout on screen
g.translate(loc.getX(), loc.getY());
Shape[] carets = layout.getCaretShapes(next.getInsertionIndex());
g.draw(carets[0]);
if (carets[1] != null) {
g.draw(carets[1]);
}
}
绘制与源文本中的子字符串对应的选择范围。 所选区域可能在视觉上不连续:
// selStart, selLimit should be relative to the layout,
// not to the source text
int selStart = ..., selLimit = ...;
Color selectionColor = ...;
Shape selection = layout.getLogicalHighlightShape(selStart, selLimit);
// selection may consist of disjoint areas
// graphics is assumed to be translated to origin of layout
g.setColor(selectionColor);
g.fill(selection);
绘制视觉上连续的选择范围。 选择范围可以对应于源文本中的多于一个子字符串。 可以使用getLogicalRangesForVisualSelection()获取相应源文本子字符串的范围:
TextHitInfo selStart = ..., selLimit = ...;
Shape selection = layout.getVisualHighlightShape(selStart, selLimit);
g.setColor(selectionColor);
g.fill(selection);
int[] ranges = getLogicalRangesForVisualSelection(selStart, selLimit);
// ranges[0], ranges[1] is the first selection range,
// ranges[2], ranges[3] is the second selection range, etc.
注意:字体旋转可能导致文本基线旋转,并且具有不同旋转的多次运行可能导致基线弯曲或锯齿形。 为了解释这种(罕见的)可能性,指定了一些API来返回度量并在基线相对坐标中获取参数(例如,上升,前进),而其他API则在“标准坐标”中(例如,getBounds)。 基线相对坐标中的值将'x'坐标映射到沿基线的距离(正x沿基线向前),'y'坐标沿'x'处的基线垂线的距离(正) y从基线矢量顺时针90度)。 标准坐标中的值沿x轴和y轴测量,TextLayout原点为0,0。 每个相关API的文档都指出了什么值在哪个坐标系中。 通常,与测量相关的API在基线相对坐标中,而与显示相关的API在标准坐标中。