TextLayout
is an immutable graphical representation of styled
character data.
It provides the following capabilities:
A TextLayout
object can be rendered using
its draw
method.
TextLayout
can be constructed either directly or through
the use of a LineBreakMeasurer
. When constructed directly, the
source text represents a single paragraph. LineBreakMeasurer
allows styled text to be broken into lines that fit within a particular
width. See the LineBreakMeasurer
documentation for more
information.
TextLayout
construction logically proceeds as follows:
TextAttribute.FONT
is present, otherwise by computing
a default font using the attributes that have been defined
All graphical information returned from a TextLayout
object's methods is relative to the origin of the
TextLayout
, which is the intersection of the
TextLayout
object's baseline with its left edge. Also,
coordinates passed into a TextLayout
object's methods
are assumed to be relative to the TextLayout
object's
origin. Clients usually need to translate between a
TextLayout
object's coordinate system and the coordinate
system in another object (such as a
Graphics
object).
TextLayout
objects are constructed from styled text,
but they do not retain a reference to their source text. Thus,
changes in the text previously used to generate a TextLayout
do not affect the TextLayout
.
Three methods on a TextLayout
object
(getNextRightHit
, getNextLeftHit
, and
hitTestChar
) return instances of TextHitInfo
.
The offsets contained in these TextHitInfo
objects
are relative to the start of the TextLayout
, not
to the text used to create the TextLayout
. Similarly,
TextLayout
methods that accept TextHitInfo
instances as parameters expect the TextHitInfo
object's
offsets to be relative to the TextLayout
, not to any
underlying text storage model.
Examples:
Constructing and drawing a TextLayout
and its bounding
rectangle:
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);
Hit-testing a TextLayout
(determining which character is at
a particular graphical location):
Point2D click = ...; TextHitInfo hit = layout.hitTestChar( (float) (click.getX() - loc.getX()), (float) (click.getY() - loc.getY()));
Responding to a right-arrow key press:
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]); } }
Drawing a selection range corresponding to a substring in the source text. The selected area may not be visually contiguous:
// 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 tranlated to origin of layout g.setColor(selectionColor); g.fill(selection);
Drawing a visually contiguous selection range. The selection range may
correspond to more than one substring in the source text. The ranges of
the corresponding source text substrings can be obtained with
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.
Note: Font rotations can cause text baselines to be rotated, and multiple runs with different rotations can cause the baseline to bend or zig-zag. In order to account for this (rare) possibility, some APIs are specified to return metrics and take parameters 'in baseline-relative coordinates' (e.g. ascent, advance), and others are in 'in standard coordinates' (e.g. getBounds). Values in baseline-relative coordinates map the 'x' coordinate to the distance along the baseline, (positive x is forward along the baseline), and the 'y' coordinate to a distance along the perpendicular to the baseline at 'x' (postitive y is 90 degrees clockwise from the baseline vector). Values in standard coordinates are measured along the x and y axes, with 0,0 at the origin of the TextLayout. Documentation for each relevant API indicates what values are in what coordinate system. In general, measurement-related APIs are in baseline-relative coordinates, while display-related APIs are in standard coordinates.
implements
LineBreakMeasurer, TextAttribute, TextHitInfo, LayoutPath