FileDocCategorySizeDatePackage
TextLayout.javaAPI DocAndroid 1.5 API31992Wed May 06 22:41:54 BST 2009java.awt.font

TextLayout

public final class TextLayout extends Object implements Cloneable
The TextLayout class defines the graphical representation of character data. This class provides method for obtaining information about cursor positioning and movement, split cursors for text with different directions, logical and visual highlighting, multiple baselines, hits, justification, ascent, descent, and advance, and rendering. A TextLayout object can be rendered using Graphics context.
since
Android 1.0

Fields Summary
public static final CaretPolicy
DEFAULT_CARET_POLICY
The Constant DEFAULT_CARET_POLICY indicates the default caret policy.
private org.apache.harmony.awt.gl.font.TextRunBreaker
breaker
The breaker.
private boolean
metricsValid
The metrics valid.
private org.apache.harmony.awt.gl.font.TextMetricsCalculator
tmc
The tmc.
private org.apache.harmony.awt.gl.font.BasicMetrics
metrics
The metrics.
private org.apache.harmony.awt.gl.font.CaretManager
caretManager
The caret manager.
float
justificationWidth
The justification width.
Constructors Summary
public TextLayout(String string, Font font, FontRenderContext frc)
Instantiates a new TextLayout object from the specified string and Font.

param
string the string to be displayed.
param
font the font of the text.
param
frc the FontRenderContext object for obtaining information about a graphics device.


                                                                                           
           
        if (string == null) {
            // awt.01='{0}' parameter is null
            throw new IllegalArgumentException(Messages.getString("awt.01", "string")); //$NON-NLS-1$ //$NON-NLS-2$
        }

        if (font == null) {
            // awt.01='{0}' parameter is null
            throw new IllegalArgumentException(Messages.getString("awt.01", "font")); //$NON-NLS-1$ //$NON-NLS-2$
        }

        if (string.length() == 0) {
            // awt.02='{0}' parameter has zero length
            throw new IllegalArgumentException(Messages.getString("awt.02", "string")); //$NON-NLS-1$ //$NON-NLS-2$
        }

        AttributedString as = new AttributedString(string);
        as.addAttribute(TextAttribute.FONT, font);
        this.breaker = new TextRunBreaker(as.getIterator(), frc);
        caretManager = new CaretManager(breaker);
    
public TextLayout(String string, Map attributes, FontRenderContext frc)
Instantiates a new TextLayout from the specified text and a map of attributes.

param
string the string to be displayed.
param
attributes the attributes to be used for obtaining the text style.
param
frc the FontRenderContext object for obtaining information about a graphics device.

        if (string == null) {
            // awt.01='{0}' parameter is null
            throw new IllegalArgumentException(Messages.getString("awt.01", "string")); //$NON-NLS-1$ //$NON-NLS-2$
        }

        if (attributes == null) {
            // awt.01='{0}' parameter is null
            throw new IllegalArgumentException(Messages.getString("awt.01", "attributes")); //$NON-NLS-1$ //$NON-NLS-2$
        }

        if (string.length() == 0) {
            // awt.02='{0}' parameter has zero length
            throw new IllegalArgumentException(Messages.getString("awt.02", "string")); //$NON-NLS-1$ //$NON-NLS-2$
        }

        AttributedString as = new AttributedString(string);
        as.addAttributes(attributes, 0, string.length());
        this.breaker = new TextRunBreaker(as.getIterator(), frc);
        caretManager = new CaretManager(breaker);
    
public TextLayout(AttributedCharacterIterator text, FontRenderContext frc)
Instantiates a new TextLayout from the AttributedCharacterIterator.

param
text the AttributedCharacterIterator.
param
frc the FontRenderContext object for obtaining information about a graphics device.

        if (text == null) {
            // awt.03='{0}' iterator parameter is null
            throw new IllegalArgumentException(Messages.getString("awt.03", "text")); //$NON-NLS-1$ //$NON-NLS-2$
        }

        if (text.getBeginIndex() == text.getEndIndex()) {
            // awt.04='{0}' iterator parameter has zero length
            throw new IllegalArgumentException(Messages.getString("awt.04", "text")); //$NON-NLS-1$ //$NON-NLS-2$
        }

        this.breaker = new TextRunBreaker(text, frc);
        caretManager = new CaretManager(breaker);
    
TextLayout(org.apache.harmony.awt.gl.font.TextRunBreaker breaker)
Instantiates a new text layout.

param
breaker the breaker.

        this.breaker = breaker;
        caretManager = new CaretManager(this.breaker);
    
Methods Summary
protected java.lang.Objectclone()
Returns a copy of this object.

return
a copy of this object.

        TextLayout res = new TextLayout((TextRunBreaker)breaker.clone());

        if (justificationWidth >= 0) {
            res.handleJustify(justificationWidth);
        }

        return res;
    
public voiddraw(java.awt.Graphics2D g2d, float x, float y)
Draws this TextLayout at the specified location with the specified Graphics2D context.

param
g2d the Graphics2D object which renders this TextLayout.
param
x the X coordinate of the TextLayout origin.
param
y the Y coordinate of the TextLayout origin.

        updateMetrics();
        breaker.drawSegments(g2d, x, y);
    
public booleanequals(java.awt.font.TextLayout layout)
Compares this TextLayout object to the specified TextLayout object.

param
layout the TextLayout object to be compared.
return
true, if this TextLayout object is equal to the specified TextLayout object, false otherwise.

        if (layout == null) {
            return false;
        }
        return this.breaker.equals(layout.breaker);
    
public booleanequals(java.lang.Object obj)
Compares this TextLayout object to the specified Object.

param
obj the Object to be compared.
return
true, if this TextLayout object is equal to the specified Object, false otherwise.

        return obj instanceof TextLayout ? equals((TextLayout)obj) : false;
    
public floatgetAdvance()
Gets the advance of this TextLayout object.

return
the advance of this TextLayout object.

        updateMetrics();
        return metrics.getAdvance();
    
public floatgetAscent()
Gets the ascent of this TextLayout object.

return
the ascent of this TextLayout object.

        updateMetrics();
        return metrics.getAscent();
    
public bytegetBaseline()
Gets the baseline of this TextLayout object.

return
the baseline of this TextLayout object.

        updateMetrics();
        return (byte)metrics.getBaseLineIndex();
    
public float[]getBaselineOffsets()
Gets the float array of offsets for the baselines which are used in this TextLayout.

return
the float array of offsets for the baselines which are used in this TextLayout.

        updateMetrics();
        return tmc.getBaselineOffsets();
    
public java.awt.ShapegetBlackBoxBounds(int firstEndpoint, int secondEndpoint)
Gets the black box bounds of the characters in the specified area. The black box bounds is an Shape which contains all bounding boxes of all the glyphs of the characters between firstEndpoint and secondEndpoint parameters values.

param
firstEndpoint the first point of the area.
param
secondEndpoint the second point of the area.
return
the Shape which contains black box bounds.

        updateMetrics();
        if (firstEndpoint < secondEndpoint) {
            return breaker.getBlackBoxBounds(firstEndpoint, secondEndpoint);
        }
        return breaker.getBlackBoxBounds(secondEndpoint, firstEndpoint);
    
public java.awt.geom.Rectangle2DgetBounds()
Gets the bounds of this TextLayout.

return
the bounds of this TextLayout.

        updateMetrics();
        return breaker.getVisualBounds();
    
public float[]getCaretInfo(java.awt.font.TextHitInfo hitInfo)
Gets information about the caret of the specified TextHitInfo.

param
hitInfo the TextHitInfo.
return
the information about the caret of the specified TextHitInfo.

        updateMetrics();
        return caretManager.getCaretInfo(hitInfo);
    
public float[]getCaretInfo(java.awt.font.TextHitInfo hitInfo, java.awt.geom.Rectangle2D bounds)
Gets information about the caret of the specified TextHitInfo of a character in this TextLayout.

param
hitInfo the TextHitInfo of a character in this TextLayout.
param
bounds the bounds to which the caret info is constructed.
return
the caret of the specified TextHitInfo.

        updateMetrics();
        return caretManager.getCaretInfo(hitInfo);
    
public java.awt.ShapegetCaretShape(java.awt.font.TextHitInfo hitInfo, java.awt.geom.Rectangle2D bounds)
Gets a Shape which represents the caret of the specified TextHitInfo in the bounds of this TextLayout.

param
hitInfo the TextHitInfo.
param
bounds the bounds to which the caret info is constructed.
return
the Shape which represents the caret.

        updateMetrics();
        return caretManager.getCaretShape(hitInfo, this);
    
public java.awt.ShapegetCaretShape(java.awt.font.TextHitInfo hitInfo)
Gets a Shape which represents the caret of the specified TextHitInfo in the bounds of this TextLayout.

param
hitInfo the TextHitInfo.
return
the Shape which represents the caret.

        updateMetrics();
        return caretManager.getCaretShape(hitInfo, this);
    
public java.awt.Shape[]getCaretShapes(int offset)
Gets two Shapes for the strong and weak carets with default caret policy and null bounds: the first element is the strong caret, the second is the weak caret or null.

param
offset an offset in the TextLayout.
return
an array of two Shapes corresponded to the strong and weak carets.

        return getCaretShapes(offset, null, TextLayout.DEFAULT_CARET_POLICY);
    
public java.awt.Shape[]getCaretShapes(int offset, java.awt.geom.Rectangle2D bounds)
Gets two Shapes for the strong and weak carets with the default caret policy: the first element is the strong caret, the second is the weak caret or null.

param
offset an offset in the TextLayout.
param
bounds the bounds to which to extend the carets.
return
an array of two Shapes corresponded to the strong and weak carets.

        return getCaretShapes(offset, bounds, TextLayout.DEFAULT_CARET_POLICY);
    
public java.awt.Shape[]getCaretShapes(int offset, java.awt.geom.Rectangle2D bounds, java.awt.font.TextLayout$CaretPolicy policy)
Gets two Shapes for the strong and weak carets: the first element is the strong caret, the second is the weak caret or null.

param
offset an offset in the TextLayout.
param
bounds the bounds to which to extend the carets.
param
policy the specified CaretPolicy.
return
an array of two Shapes corresponded to the strong and weak carets.

        if (offset < 0 || offset > breaker.getCharCount()) {
            // awt.195=Offset is out of bounds
            throw new IllegalArgumentException(Messages.getString("awt.195")); //$NON-NLS-1$
        }

        updateMetrics();
        return caretManager.getCaretShapes(offset, bounds, policy, this);
    
public intgetCharacterCount()
Gets the number of characters in this TextLayout.

return
the number of characters in this TextLayout.

        return breaker.getCharCount();
    
public bytegetCharacterLevel(int index)
Gets the level of the character with the specified index.

param
index the specified index of the character.
return
the level of the character.

        if (index == -1 || index == getCharacterCount()) {
            return (byte)breaker.getBaseLevel();
        }
        return breaker.getLevel(index);
    
public floatgetDescent()
Gets the descent of this TextLayout.

return
the descent of this TextLayout.

        updateMetrics();
        return metrics.getDescent();
    
public java.awt.font.TextLayoutgetJustifiedLayout(float justificationWidth)
Gets the TextLayout wich is justified with the specified width related to this TextLayout.

param
justificationWidth the width which is used for justification.
return
a TextLayout justified to the specified width.
throws
Error the error occures if this TextLayout has been already justified.

        float justification = breaker.getJustification();

        if (justification < 0) {
            // awt.196=Justification impossible, layout already justified
            throw new Error(Messages.getString("awt.196")); //$NON-NLS-1$
        } else if (justification == 0) {
            return this;
        }

        TextLayout justifiedLayout = new TextLayout((TextRunBreaker)breaker.clone());
        justifiedLayout.handleJustify(justificationWidth);
        return justifiedLayout;
    
public floatgetLeading()
Gets the leading of this TextLayout.

return
the leading of this TextLayout.

        updateMetrics();
        return metrics.getLeading();
    
public java.awt.ShapegetLogicalHighlightShape(int firstEndpoint, int secondEndpoint)
Gets a Shape representing the logical selection betweeen the specified endpoints and extended to the natural bounds of this TextLayout.

param
firstEndpoint the first selected endpoint within the area of characters
param
secondEndpoint the second selected endpoint within the area of characters
return
a Shape represented the logical selection betweeen the specified endpoints.

        updateMetrics();
        return getLogicalHighlightShape(firstEndpoint, secondEndpoint, breaker.getLogicalBounds());
    
public java.awt.ShapegetLogicalHighlightShape(int firstEndpoint, int secondEndpoint, java.awt.geom.Rectangle2D bounds)
Gets a Shape representing the logical selection betweeen the specified endpoints and extended to the specified bounds of this TextLayout.

param
firstEndpoint the first selected endpoint within the area of characters
param
secondEndpoint the second selected endpoint within the area of characters
param
bounds the specified bounds of this TextLayout.
return
a Shape represented the logical selection betweeen the specified endpoints.

        updateMetrics();

        if (firstEndpoint > secondEndpoint) {
            if (secondEndpoint < 0 || firstEndpoint > breaker.getCharCount()) {
                // awt.197=Endpoints are out of range
                throw new IllegalArgumentException(Messages.getString("awt.197")); //$NON-NLS-1$
            }
            return caretManager.getLogicalHighlightShape(secondEndpoint, firstEndpoint, bounds,
                    this);
        }
        if (firstEndpoint < 0 || secondEndpoint > breaker.getCharCount()) {
            // awt.197=Endpoints are out of range
            throw new IllegalArgumentException(Messages.getString("awt.197")); //$NON-NLS-1$
        }
        return caretManager.getLogicalHighlightShape(firstEndpoint, secondEndpoint, bounds, this);
    
public int[]getLogicalRangesForVisualSelection(java.awt.font.TextHitInfo hit1, java.awt.font.TextHitInfo hit2)
Gets the logical ranges of text which corresponds to a visual selection.

param
hit1 the first endpoint of the visual range.
param
hit2 the second endpoint of the visual range.
return
the logical ranges of text which corresponds to a visual selection.

        return caretManager.getLogicalRangesForVisualSelection(hit1, hit2);
    
public java.awt.font.TextHitInfogetNextLeftHit(int offset)
Gets the TextHitInfo for the next caret to the left (or up at the end of the line) of the specified offset.

param
offset the offset in this TextLayout.
return
the TextHitInfo for the next caret to the left (or up at the end of the line) of the specified hit, or null if there is no hit.

        return getNextLeftHit(offset, DEFAULT_CARET_POLICY);
    
public java.awt.font.TextHitInfogetNextLeftHit(java.awt.font.TextHitInfo hitInfo)
Gets the TextHitInfo for the next caret to the left (or up at the end of the line) of the specified hit.

param
hitInfo the initial hit.
return
the TextHitInfo for the next caret to the left (or up at the end of the line) of the specified hit, or null if there is no hit.

        breaker.createAllSegments();
        return caretManager.getNextLeftHit(hitInfo);
    
public java.awt.font.TextHitInfogetNextLeftHit(int offset, java.awt.font.TextLayout$CaretPolicy policy)
Gets the TextHitInfo for the next caret to the left (or up at the end of the line) of the specified offset, given the specified caret policy.

param
offset the offset in this TextLayout.
param
policy the policy to be used for obtaining the strong caret.
return
the TextHitInfo for the next caret to the left of the specified offset, or null if there is no hit.

        if (offset < 0 || offset > breaker.getCharCount()) {
            // awt.195=Offset is out of bounds
            throw new IllegalArgumentException(Messages.getString("awt.195")); //$NON-NLS-1$
        }

        TextHitInfo hit = TextHitInfo.afterOffset(offset);
        TextHitInfo strongHit = policy.getStrongCaret(hit, hit.getOtherHit(), this);
        TextHitInfo nextLeftHit = getNextLeftHit(strongHit);

        if (nextLeftHit != null) {
            return policy.getStrongCaret(getVisualOtherHit(nextLeftHit), nextLeftHit, this);
        }
        return null;
    
public java.awt.font.TextHitInfogetNextRightHit(java.awt.font.TextHitInfo hitInfo)
Gets the TextHitInfo for the next caret to the right (or down at the end of the line) of the specified hit.

param
hitInfo the initial hit.
return
the TextHitInfo for the next caret to the right (or down at the end of the line) of the specified hit, or null if there is no hit.

        breaker.createAllSegments();
        return caretManager.getNextRightHit(hitInfo);
    
public java.awt.font.TextHitInfogetNextRightHit(int offset)
Gets the TextHitInfo for the next caret to the right (or down at the end of the line) of the specified offset.

param
offset the offset in this TextLayout.
return
the TextHitInfo for the next caret to the right of the specified offset, or null if there is no hit.

        return getNextRightHit(offset, DEFAULT_CARET_POLICY);
    
public java.awt.font.TextHitInfogetNextRightHit(int offset, java.awt.font.TextLayout$CaretPolicy policy)
Gets the TextHitInfo for the next caret to the right (or down at the end of the line) of the specified offset, given the specified caret policy.

param
offset the offset in this TextLayout.
param
policy the policy to be used for obtaining the strong caret.
return
the TextHitInfo for the next caret to the right of the specified offset, or null if there is no hit.

        if (offset < 0 || offset > breaker.getCharCount()) {
            // awt.195=Offset is out of bounds
            throw new IllegalArgumentException(Messages.getString("awt.195")); //$NON-NLS-1$
        }

        TextHitInfo hit = TextHitInfo.afterOffset(offset);
        TextHitInfo strongHit = policy.getStrongCaret(hit, hit.getOtherHit(), this);
        TextHitInfo nextRightHit = getNextRightHit(strongHit);

        if (nextRightHit != null) {
            return policy.getStrongCaret(getVisualOtherHit(nextRightHit), nextRightHit, this);
        }
        return null;
    
public java.awt.ShapegetOutline(java.awt.geom.AffineTransform xform)
Gets the outline of this TextLayout as a Shape.

param
xform the AffineTransform to be used to transform the outline before returning it, or null if no transformation is desired.
return
the outline of this TextLayout as a Shape.

        breaker.createAllSegments();

        GeneralPath outline = breaker.getOutline();

        if (outline != null && xform != null) {
            outline.transform(xform);
        }

        return outline;
    
public floatgetVisibleAdvance()
Gets the visible advance of this TextLayout which is defined as diffence between leading (advance) and trailing whitespace.

return
the visible advance of this TextLayout.

        updateMetrics();

        // Trailing whitespace _SHOULD_ be reordered (Unicode spec) to
        // base direction, so it is also trailing
        // in logical representation. We use this fact.
        int lastNonWhitespace = breaker.getLastNonWhitespace();

        if (lastNonWhitespace < 0) {
            return 0;
        } else if (lastNonWhitespace == getCharacterCount() - 1) {
            return getAdvance();
        } else if (justificationWidth >= 0) { // Layout is justified
            return justificationWidth;
        } else {
            breaker.pushSegments(breaker.getACI().getBeginIndex(), lastNonWhitespace
                    + breaker.getACI().getBeginIndex() + 1);

            breaker.createAllSegments();

            float visAdvance = tmc.createMetrics().getAdvance();

            breaker.popSegments();
            return visAdvance;
        }
    
public java.awt.ShapegetVisualHighlightShape(java.awt.font.TextHitInfo hit1, java.awt.font.TextHitInfo hit2, java.awt.geom.Rectangle2D bounds)
Gets a Shape which corresponds to the highlighted (selected) area based on two hit locations within the text and extends to the bounds.

param
hit1 the first text hit location.
param
hit2 the second text hit location.
param
bounds the rectangle that the highlighted area should be extended or restricted to.
return
a Shape which corresponds to the highlighted (selected) area.

        return caretManager.getVisualHighlightShape(hit1, hit2, bounds, this);
    
public java.awt.ShapegetVisualHighlightShape(java.awt.font.TextHitInfo hit1, java.awt.font.TextHitInfo hit2)
Gets a Shape which corresponds to the highlighted (selected) area based on two hit locations within the text.

param
hit1 the first text hit location.
param
hit2 the second text hit location.
return
a Shape which corresponds to the highlighted (selected) area.

        breaker.createAllSegments();
        return caretManager.getVisualHighlightShape(hit1, hit2, breaker.getLogicalBounds(), this);
    
public java.awt.font.TextHitInfogetVisualOtherHit(java.awt.font.TextHitInfo hitInfo)
Gets the TextHitInfo for a hit on the opposite side of the specified hit's caret.

param
hitInfo the specified TextHitInfo.
return
the TextHitInfo for a hit on the opposite side of the specified hit's caret.

        return caretManager.getVisualOtherHit(hitInfo);
    
protected voidhandleJustify(float justificationWidth)
Justifies the text; this method should be overridden by subclasses.

param
justificationWidth the width for justification.

        float justification = breaker.getJustification();

        if (justification < 0) {
            // awt.196=Justification impossible, layout already justified
            throw new IllegalStateException(Messages.getString("awt.196")); //$NON-NLS-1$
        } else if (justification == 0) {
            return;
        }

        float gap = (justificationWidth - getVisibleAdvance()) * justification;
        breaker.justify(gap);
        this.justificationWidth = justificationWidth;

        // Correct metrics
        tmc = new TextMetricsCalculator(breaker);
        tmc.correctAdvance(metrics);
    
public inthashCode()
Returns a hash code of this TextLayout object.

return
a hash code of this TextLayout object.

        return breaker.hashCode();
    
public java.awt.font.TextHitInfohitTestChar(float x, float y)
Returns a TextHitInfo object that gives information on which division point (between two characters) is corresponds to a hit (such as a mouse click) at the specified coordinates.

param
x the X coordinate in this TextLayout.
param
y the Y coordinate in this TextLayout. TextHitInfo object corresponding to the given coordinates within the text.
return
the information about the character at the specified position.

        return hitTestChar(x, y, getBounds());
    
public java.awt.font.TextHitInfohitTestChar(float x, float y, java.awt.geom.Rectangle2D bounds)
Returns a TextHitInfo object that gives information on which division point (between two characters) is corresponds to a hit (such as a mouse click) at the specified coordinates within the specified text rectangle.

param
x the X coordinate in this TextLayout.
param
y the Y coordinate in this TextLayout.
param
bounds the bounds of the text area. TextHitInfo object corresponding to the given coordinates within the text.
return
the information about the character at the specified position.

        if (x > bounds.getMaxX()) {
            return breaker.isLTR() ? TextHitInfo.trailing(breaker.getCharCount() - 1) : TextHitInfo
                    .leading(0);
        }

        if (x < bounds.getMinX()) {
            return breaker.isLTR() ? TextHitInfo.leading(0) : TextHitInfo.trailing(breaker
                    .getCharCount() - 1);
        }

        return breaker.hitTest(x, y);
    
public booleanisLeftToRight()
Returns true if this TextLayout has a "left to right" direction.

return
true if this TextLayout has a "left to right" direction, false if this TextLayout has a "right to left" direction.

        return breaker.isLTR();
    
public booleanisVertical()
Returns true if this TextLayout is vertical, false otherwise.

return
true if this TextLayout is vertical, false if horizontal.

        return false;
    
public java.lang.StringtoString()
Gets the string representation for this TextLayout.

return
the string representation for this TextLayout.

 // what for?
        return super.toString();
    
private voidupdateMetrics()
Update metrics.

        if (!metricsValid) {
            breaker.createAllSegments();
            tmc = new TextMetricsCalculator(breaker);
            metrics = tmc.createMetrics();
            metricsValid = true;
        }