/*
 * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * (C) Copyright Taligent, Inc. 1996 - 1997, All Rights Reserved
 * (C) Copyright IBM Corp. 1996-2003, All Rights Reserved
 *
 * The original version of this source code and documentation is
 * copyrighted and owned by Taligent, Inc., a wholly-owned subsidiary
 * of IBM. These materials are provided under terms of a License
 * Agreement between Taligent and Sun. This technology is protected
 * by multiple US and International patents.
 *
 * This notice and attribution to Taligent may not be removed.
 * Taligent is a registered trademark of Taligent, Inc.
 *
 */

package java.awt.font;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.font.NumericShaper;
import java.awt.font.TextLine.TextLineMetrics;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.text.AttributedString;
import java.text.AttributedCharacterIterator;
import java.text.AttributedCharacterIterator.Attribute;
import java.util.Map;
import java.util.HashMap;
import java.util.Hashtable;
import sun.font.AttributeValues;
import sun.font.CoreMetrics;
import sun.font.Decoration;
import sun.font.FontLineMetrics;
import sun.font.FontResolver;
import sun.font.GraphicComponent;
import sun.font.LayoutPathImpl;
import sun.text.CodePointIterator;

/**
 *
 * <code>TextLayout</code> is an immutable graphical representation of styled
 * character data.
 * <p>
 * It provides the following capabilities:
 * <ul>
 * <li>implicit bidirectional analysis and reordering,
 * <li>cursor positioning and movement, including split cursors for
 * mixed directional text,
 * <li>highlighting, including both logical and visual highlighting
 * for mixed directional text,
 * <li>multiple baselines (roman, hanging, and centered),
 * <li>hit testing,
 * <li>justification,
 * <li>default font substitution,
 * <li>metric information such as ascent, descent, and advance, and
 * <li>rendering
 * </ul>
 * <p>
 * A <code>TextLayout</code> object can be rendered using
 * its <code>draw</code> method.
 * <p>
 * <code>TextLayout</code> can be constructed either directly or through
 * the use of a {@link LineBreakMeasurer}.  When constructed directly, the
 * source text represents a single paragraph.  <code>LineBreakMeasurer</code>
 * allows styled text to be broken into lines that fit within a particular
 * width.  See the <code>LineBreakMeasurer</code> documentation for more
 * information.
 * <p>
 * <code>TextLayout</code> construction logically proceeds as follows:
 * <ul>
 * <li>paragraph attributes are extracted and examined,
 * <li>text is analyzed for bidirectional reordering, and reordering
 * information is computed if needed,
 * <li>text is segmented into style runs
 * <li>fonts are chosen for style runs, first by using a font if the
 * attribute {@link TextAttribute#FONT} is present, otherwise by computing
 * a default font using the attributes that have been defined
 * <li>if text is on multiple baselines, the runs or subruns are further
 * broken into subruns sharing a common baseline,
 * <li>glyphvectors are generated for each run using the chosen font,
 * <li>final bidirectional reordering is performed on the glyphvectors
 * </ul>
 * <p>
 * All graphical information returned from a <code>TextLayout</code>
 * object's methods is relative to the origin of the
 * <code>TextLayout</code>, which is the intersection of the
 * <code>TextLayout</code> object's baseline with its left edge.  Also,
 * coordinates passed into a <code>TextLayout</code> object's methods
 * are assumed to be relative to the <code>TextLayout</code> object's
 * origin.  Clients usually need to translate between a
 * <code>TextLayout</code> object's coordinate system and the coordinate
 * system in another object (such as a
 * {@link java.awt.Graphics Graphics} object).
 * <p>
 * <code>TextLayout</code> 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 <code>TextLayout</code>
 * do not affect the <code>TextLayout</code>.
 * <p>
 * Three methods on a <code>TextLayout</code> object
 * (<code>getNextRightHit</code>, <code>getNextLeftHit</code>, and
 * <code>hitTestChar</code>) return instances of {@link TextHitInfo}.
 * The offsets contained in these <code>TextHitInfo</code> objects
 * are relative to the start of the <code>TextLayout</code>, <b>not</b>
 * to the text used to create the <code>TextLayout</code>.  Similarly,
 * <code>TextLayout</code> methods that accept <code>TextHitInfo</code>
 * instances as parameters expect the <code>TextHitInfo</code> object's
 * offsets to be relative to the <code>TextLayout</code>, not to any
 * underlying text storage model.
 * <p>
 * <strong>Examples</strong>:<p>
 * Constructing and drawing a <code>TextLayout</code> and its bounding
 * rectangle:
 * <blockquote><pre>
 *   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);
 * </pre>
 * </blockquote>
 * <p>
 * Hit-testing a <code>TextLayout</code> (determining which character is at
 * a particular graphical location):
 * <blockquote><pre>
 *   Point2D click = ...;
 *   TextHitInfo hit = layout.hitTestChar(
 *                         (float) (click.getX() - loc.getX()),
 *                         (float) (click.getY() - loc.getY()));
 * </pre>
 * </blockquote>
 * <p>
 * Responding to a right-arrow key press:
 * <blockquote><pre>
 *   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]);
 *       }
 *   }
 * </pre></blockquote>
 * <p>
 * Drawing a selection range corresponding to a substring in the source text.
 * The selected area may not be visually contiguous:
 * <blockquote><pre>
 *   // 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);
 * </pre></blockquote>
 * <p>
 * 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
 * <code>getLogicalRangesForVisualSelection()</code>:
 * <blockquote><pre>
 *   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.
 * </pre></blockquote>
 * <p>
 * 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.
 *
 * @see LineBreakMeasurer
 * @see TextAttribute
 * @see TextHitInfo
 * @see LayoutPath
 */
public final class TextLayout implements Cloneable {

    private int characterCount;
    private boolean isVerticalLine = false;
    private byte baseline;
    private float[] baselineOffsets;  // why have these ?
    private TextLine textLine;

    // cached values computed from GlyphSets and set info:
    // all are recomputed from scratch in buildCache()
    private TextLine.TextLineMetrics lineMetrics = null;
    private float visibleAdvance;
    private int hashCodeCache;

    /*
     * TextLayouts are supposedly immutable.  If you mutate a TextLayout under
     * the covers (like the justification code does) you'll need to set this
     * back to false.  Could be replaced with textLine != null <--> cacheIsValid.
     */
    private boolean cacheIsValid = false;


    // This value is obtained from an attribute, and constrained to the
    // interval [0,1].  If 0, the layout cannot be justified.
    private float justifyRatio;

    // If a layout is produced by justification, then that layout
    // cannot be justified.  To enforce this constraint the
    // justifyRatio of the justified layout is set to this value.
    private static final float ALREADY_JUSTIFIED = -53.9f;

    // dx and dy specify the distance between the TextLayout's origin
    // and the origin of the leftmost GlyphSet (TextLayoutComponent,
    // actually).  They were used for hanging punctuation support,
    // which is no longer implemented.  Currently they are both always 0,
    // and TextLayout is not guaranteed to work with non-zero dx, dy
    // values right now.  They were left in as an aide and reminder to
    // anyone who implements hanging punctuation or other similar stuff.
    // They are static now so they don't take up space in TextLayout
    // instances.
    private static float dx;
    private static float dy;

    /*
     * Natural bounds is used internally.  It is built on demand in
     * getNaturalBounds.
     */
    private Rectangle2D naturalBounds = null;

    /*
     * boundsRect encloses all of the bits this TextLayout can draw.  It
     * is build on demand in getBounds.
     */
    private Rectangle2D boundsRect = null;

    /*
     * flag to supress/allow carets inside of ligatures when hit testing or
     * arrow-keying
     */
    private boolean caretsInLigaturesAreAllowed = false;

    /**
     * Defines a policy for determining the strong caret location.
     * This class contains one method, <code>getStrongCaret</code>, which
     * is used to specify the policy that determines the strong caret in
     * dual-caret text.  The strong caret is used to move the caret to the
     * left or right. Instances of this class can be passed to
     * <code>getCaretShapes</code>, <code>getNextLeftHit</code> and
     * <code>getNextRightHit</code> to customize strong caret
     * selection.
     * <p>
     * To specify alternate caret policies, subclass <code>CaretPolicy</code>
     * and override <code>getStrongCaret</code>.  <code>getStrongCaret</code>
     * should inspect the two <code>TextHitInfo</code> arguments and choose
     * one of them as the strong caret.
     * <p>
     * Most clients do not need to use this class.
     */
    public static class CaretPolicy {

        /**
         * Constructs a <code>CaretPolicy</code>.
         */
         public CaretPolicy() {
         }

        /**
         * Chooses one of the specified <code>TextHitInfo</code> instances as
         * a strong caret in the specified <code>TextLayout</code>.
         * @param hit1 a valid hit in <code>layout</code>
         * @param hit2 a valid hit in <code>layout</code>
         * @param layout the <code>TextLayout</code> in which
         *        <code>hit1</code> and <code>hit2</code> are used
         * @return <code>hit1</code> or <code>hit2</code>
         *        (or an equivalent <code>TextHitInfo</code>), indicating the
         *        strong caret.
         */
        public TextHitInfo getStrongCaret(TextHitInfo hit1,
                                          TextHitInfo hit2,
                                          TextLayout layout) {

            // default implmentation just calls private method on layout
            return layout.getStrongHit(hit1, hit2);
        }
    }

    /**
     * This <code>CaretPolicy</code> is used when a policy is not specified
     * by the client.  With this policy, a hit on a character whose direction
     * is the same as the line direction is stronger than a hit on a
     * counterdirectional character.  If the characters' directions are
     * the same, a hit on the leading edge of a character is stronger
     * than a hit on the trailing edge of a character.
     */
    public static final CaretPolicy DEFAULT_CARET_POLICY = new CaretPolicy();

    /**
     * Constructs a <code>TextLayout</code> from a <code>String</code>
     * and a {@link Font}.  All the text is styled using the specified
     * <code>Font</code>.
     * <p>
     * The <code>String</code> must specify a single paragraph of text,
     * because an entire paragraph is required for the bidirectional
     * algorithm.
     * @param string the text to display
     * @param font a <code>Font</code> used to style the text
     * @param frc contains information about a graphics device which is needed
     *       to measure the text correctly.
     *       Text measurements can vary slightly depending on the
     *       device resolution, and attributes such as antialiasing.  This
     *       parameter does not specify a translation between the
     *       <code>TextLayout</code> and user space.
     */
    public TextLayout(String string, Font font, FontRenderContext frc) {

        if (font == null) {
            throw new IllegalArgumentException("Null font passed to TextLayout constructor.");
        }

        if (string == null) {
            throw new IllegalArgumentException("Null string passed to TextLayout constructor.");
        }

        if (string.length() == 0) {
            throw new IllegalArgumentException("Zero length string passed to TextLayout constructor.");
        }

        Map attributes = null;
        if (font.hasLayoutAttributes()) {
            attributes = font.getAttributes();
        }

        char[] text = string.toCharArray();
        if (sameBaselineUpTo(font, text, 0, text.length) == text.length) {
            fastInit(text, font, attributes, frc);
        } else {
            AttributedString as = attributes == null
                ? new AttributedString(string)
                : new AttributedString(string, attributes);
            as.addAttribute(TextAttribute.FONT, font);
            standardInit(as.getIterator(), text, frc);
        }
    }

    /**
     * Constructs a <code>TextLayout</code> from a <code>String</code>
     * and an attribute set.
     * <p>
     * All the text is styled using the provided attributes.
     * <p>
     * <code>string</code> must specify a single paragraph of text because an
     * entire paragraph is required for the bidirectional algorithm.
     * @param string the text to display
     * @param attributes the attributes used to style the text
     * @param frc contains information about a graphics device which is needed
     *       to measure the text correctly.
     *       Text measurements can vary slightly depending on the
     *       device resolution, and attributes such as antialiasing.  This
     *       parameter does not specify a translation between the
     *       <code>TextLayout</code> and user space.
     */
    public TextLayout(String string, Map<? extends Attribute,?> attributes,
                      FontRenderContext frc)
    {
        if (string == null) {
            throw new IllegalArgumentException("Null string passed to TextLayout constructor.");
        }

        if (attributes == null) {
            throw new IllegalArgumentException("Null map passed to TextLayout constructor.");
        }

        if (string.length() == 0) {
            throw new IllegalArgumentException("Zero length string passed to TextLayout constructor.");
        }

        char[] text = string.toCharArray();
        Font font = singleFont(text, 0, text.length, attributes);
        if (font != null) {
            fastInit(text, font, attributes, frc);
        } else {
            AttributedString as = new AttributedString(string, attributes);
            standardInit(as.getIterator(), text, frc);
        }
    }

    /*
     * Determines a font for the attributes, and if a single font can render
     * all the text on one baseline, return it, otherwise null.  If the
     * attributes specify a font, assume it can display all the text without
     * checking.
     * If the AttributeSet contains an embedded graphic, return null.
     */
    private static Font singleFont(char[] text,
                                   int start,
                                   int limit,
                                   Map attributes) {

        if (attributes.get(TextAttribute.CHAR_REPLACEMENT) != null) {
            return null;
        }

        Font font = null;
        try {
            font = (Font)attributes.get(TextAttribute.FONT);
        }
        catch (ClassCastException e) {
        }
        if (font == null) {
            if (attributes.get(TextAttribute.FAMILY) != null) {
                font = Font.getFont(attributes);
                if (font.canDisplayUpTo(text, start, limit) != -1) {
                    return null;
                }
            } else {
                FontResolver resolver = FontResolver.getInstance();
                CodePointIterator iter = CodePointIterator.create(text, start, limit);
                int fontIndex = resolver.nextFontRunIndex(iter);
                if (iter.charIndex() == limit) {
                    font = resolver.getFont(fontIndex, attributes);
                }
            }
        }

        if (sameBaselineUpTo(font, text, start, limit) != limit) {
            return null;
        }

        return font;
    }

    /**
     * Constructs a <code>TextLayout</code> from an iterator over styled text.
     * <p>
     * The iterator must specify a single paragraph of text because an
     * entire paragraph is required for the bidirectional
     * algorithm.
     * @param text the styled text to display
     * @param frc contains information about a graphics device which is needed
     *       to measure the text correctly.
     *       Text measurements can vary slightly depending on the
     *       device resolution, and attributes such as antialiasing.  This
     *       parameter does not specify a translation between the
     *       <code>TextLayout</code> and user space.
     */
    public TextLayout(AttributedCharacterIterator text, FontRenderContext frc) {

        if (text == null) {
            throw new IllegalArgumentException("Null iterator passed to TextLayout constructor.");
        }

        int start = text.getBeginIndex();
        int limit = text.getEndIndex();
        if (start == limit) {
            throw new IllegalArgumentException("Zero length iterator passed to TextLayout constructor.");
        }

        int len = limit - start;
        text.first();
        char[] chars = new char[len];
        int n = 0;
        for (char c = text.first(); c != text.DONE; c = text.next()) {
            chars[n++] = c;
        }

        text.first();
        if (text.getRunLimit() == limit) {

            Map attributes = text.getAttributes();
            Font font = singleFont(chars, 0, len, attributes);
            if (font != null) {
                fastInit(chars, font, attributes, frc);
                return;
            }
        }

        standardInit(text, chars, frc);
    }

    /**
     * Creates a <code>TextLayout</code> from a {@link TextLine} and
     * some paragraph data.  This method is used by {@link TextMeasurer}.
     * @param textLine the line measurement attributes to apply to the
     *       the resulting <code>TextLayout</code>
     * @param baseline the baseline of the text
     * @param baselineOffsets the baseline offsets for this
     * <code>TextLayout</code>.  This should already be normalized to
     * <code>baseline</code>
     * @param justifyRatio <code>0</code> if the <code>TextLayout</code>
     *     cannot be justified; <code>1</code> otherwise.
     */
    TextLayout(TextLine textLine,
               byte baseline,
               float[] baselineOffsets,
               float justifyRatio) {

        this.characterCount = textLine.characterCount();
        this.baseline = baseline;
        this.baselineOffsets = baselineOffsets;
        this.textLine = textLine;
        this.justifyRatio = justifyRatio;
    }

    /**
     * Initialize the paragraph-specific data.
     */
    private void paragraphInit(byte aBaseline, CoreMetrics lm, Map paragraphAttrs, char[] text) {

        baseline = aBaseline;

        // normalize to current baseline
        baselineOffsets = TextLine.getNormalizedOffsets(lm.baselineOffsets, baseline);

        justifyRatio = AttributeValues.getJustification(paragraphAttrs);
        NumericShaper shaper = AttributeValues.getNumericShaping(paragraphAttrs);
        if (shaper != null) {
            shaper.shape(text, 0, text.length);
        }
    }

    /*
     * the fast init generates a single glyph set.  This requires:
     * all one style
     * all renderable by one font (ie no embedded graphics)
     * all on one baseline
     */
    private void fastInit(char[] chars, Font font, Map attrs, FontRenderContext frc) {
        // Object vf = attrs.get(TextAttribute.ORIENTATION);
        // isVerticalLine = TextAttribute.ORIENTATION_VERTICAL.equals(vf);
        isVerticalLine = false;

        LineMetrics lm = font.getLineMetrics(chars, 0, chars.length, frc);
        CoreMetrics cm = CoreMetrics.get(lm);
        byte glyphBaseline = (byte) cm.baselineIndex;

        if (attrs == null) {
            baseline = glyphBaseline;
            baselineOffsets = cm.baselineOffsets;
            justifyRatio = 1.0f;
        } else {
            paragraphInit(glyphBaseline, cm, attrs, chars);
        }

        characterCount = chars.length;

        textLine = TextLine.fastCreateTextLine(frc, chars, font, cm, attrs);
    }

    /*
     * the standard init generates multiple glyph sets based on style,
     * renderable, and baseline runs.
     * @param chars the text in the iterator, extracted into a char array
     */
    private void standardInit(AttributedCharacterIterator text, char[] chars, FontRenderContext frc) {

        characterCount = chars.length;

        // set paragraph attributes
        {
            // If there's an embedded graphic at the start of the
            // paragraph, look for the first non-graphic character
            // and use it and its font to initialize the paragraph.
            // If not, use the first graphic to initialize.

            Map paragraphAttrs = text.getAttributes();

            boolean haveFont = TextLine.advanceToFirstFont(text);

            if (haveFont) {
                Font defaultFont = TextLine.getFontAtCurrentPos(text);
                int charsStart = text.getIndex() - text.getBeginIndex();
                LineMetrics lm = defaultFont.getLineMetrics(chars, charsStart, charsStart+1, frc);
                CoreMetrics cm = CoreMetrics.get(lm);
                paragraphInit((byte)cm.baselineIndex, cm, paragraphAttrs, chars);
            }
            else {
                // hmmm what to do here?  Just try to supply reasonable
                // values I guess.

                GraphicAttribute graphic = (GraphicAttribute)
                                paragraphAttrs.get(TextAttribute.CHAR_REPLACEMENT);
                byte defaultBaseline = getBaselineFromGraphic(graphic);
                CoreMetrics cm = GraphicComponent.createCoreMetrics(graphic);
                paragraphInit(defaultBaseline, cm, paragraphAttrs, chars);
            }
        }

        textLine = TextLine.standardCreateTextLine(frc, text, chars, baselineOffsets);
    }

    /*
     * A utility to rebuild the ascent/descent/leading/advance cache.
     * You'll need to call this if you clone and mutate (like justification,
     * editing methods do)
     */
    private void ensureCache() {
        if (!cacheIsValid) {
            buildCache();
        }
    }

    private void buildCache() {
        lineMetrics = textLine.getMetrics();

        // compute visibleAdvance
        if (textLine.isDirectionLTR()) {

            int lastNonSpace = characterCount-1;
            while (lastNonSpace != -1) {
                int logIndex = textLine.visualToLogical(lastNonSpace);
                if (!textLine.isCharSpace(logIndex)) {
                    break;
                }
                else {
                    --lastNonSpace;
                }
            }
            if (lastNonSpace == characterCount-1) {
                visibleAdvance = lineMetrics.advance;
            }
            else if (lastNonSpace == -1) {
                visibleAdvance = 0;
            }
            else {
                int logIndex = textLine.visualToLogical(lastNonSpace);
                visibleAdvance = textLine.getCharLinePosition(logIndex)
                                        + textLine.getCharAdvance(logIndex);
            }
        }
        else {

            int leftmostNonSpace = 0;
            while (leftmostNonSpace != characterCount) {
                int logIndex = textLine.visualToLogical(leftmostNonSpace);
                if (!textLine.isCharSpace(logIndex)) {
                    break;
                }
                else {
                    ++leftmostNonSpace;
                }
            }
            if (leftmostNonSpace == characterCount) {
                visibleAdvance = 0;
            }
            else if (leftmostNonSpace == 0) {
                visibleAdvance = lineMetrics.advance;
            }
            else {
                int logIndex = textLine.visualToLogical(leftmostNonSpace);
                float pos = textLine.getCharLinePosition(logIndex);
                visibleAdvance = lineMetrics.advance - pos;
            }
        }

        // naturalBounds, boundsRect will be generated on demand
        naturalBounds = null;
        boundsRect = null;

        // hashCode will be regenerated on demand
        hashCodeCache = 0;

        cacheIsValid = true;
    }

    /**
     * The 'natural bounds' encloses all the carets the layout can draw.
     *
     */
    private Rectangle2D getNaturalBounds() {
        ensureCache();

        if (naturalBounds == null) {
            naturalBounds = textLine.getItalicBounds();
        }

        return naturalBounds;
    }

    /**
     * Creates a copy of this <code>TextLayout</code>.
     */
    protected Object clone() {
        /*
         * !!! I think this is safe.  Once created, nothing mutates the
         * glyphvectors or arrays.  But we need to make sure.
         * {jbr} actually, that's not quite true.  The justification code
         * mutates after cloning.  It doesn't actually change the glyphvectors
         * (that's impossible) but it replaces them with justified sets.  This
         * is a problem for GlyphIterator creation, since new GlyphIterators
         * are created by cloning a prototype.  If the prototype has outdated
         * glyphvectors, so will the new ones.  A partial solution is to set the
         * prototypical GlyphIterator to null when the glyphvectors change.  If
         * you forget this one time, you're hosed.
         */
        try {
            return super.clone();
        }
        catch (CloneNotSupportedException e) {
            throw new InternalError();
        }
    }

    /*
     * Utility to throw an expection if an invalid TextHitInfo is passed
     * as a parameter.  Avoids code duplication.
     */
    private void checkTextHit(TextHitInfo hit) {
        if (hit == null) {
            throw new IllegalArgumentException("TextHitInfo is null.");
        }

        if (hit.getInsertionIndex() < 0 ||
            hit.getInsertionIndex() > characterCount) {
            throw new IllegalArgumentException("TextHitInfo is out of range");
        }
    }

    /**
     * Creates a copy of this <code>TextLayout</code> justified to the
     * specified width.
     * <p>
     * If this <code>TextLayout</code> has already been justified, an
     * exception is thrown.  If this <code>TextLayout</code> object's
     * justification ratio is zero, a <code>TextLayout</code> identical
     * to this <code>TextLayout</code> is returned.
     * @param justificationWidth the width to use when justifying the line.
     * For best results, it should not be too different from the current
     * advance of the line.
     * @return a <code>TextLayout</code> justified to the specified width.
     * @exception Error if this layout has already been justified, an Error is
     * thrown.
     */
    public TextLayout getJustifiedLayout(float justificationWidth) {

        if (justificationWidth <= 0) {
            throw new IllegalArgumentException("justificationWidth <= 0 passed to TextLayout.getJustifiedLayout()");
        }

        if (justifyRatio == ALREADY_JUSTIFIED) {
            throw new Error("Can't justify again.");
        }

        ensureCache(); // make sure textLine is not null

        // default justification range to exclude trailing logical whitespace
        int limit = characterCount;
        while (limit > 0 && textLine.isCharWhitespace(limit-1)) {
            --limit;
        }

        TextLine newLine = textLine.getJustifiedLine(justificationWidth, justifyRatio, 0, limit);
        if (newLine != null) {
            return new TextLayout(newLine, baseline, baselineOffsets, ALREADY_JUSTIFIED);
        }

        return this;
    }

    /**
     * Justify this layout.  Overridden by subclassers to control justification
     * (if there were subclassers, that is...)
     *
     * The layout will only justify if the paragraph attributes (from the
     * source text, possibly defaulted by the layout attributes) indicate a
     * non-zero justification ratio.  The text will be justified to the
     * indicated width.  The current implementation also adjusts hanging
     * punctuation and trailing whitespace to overhang the justification width.
     * Once justified, the layout may not be rejustified.
     * <p>
     * Some code may rely on immutablity of layouts.  Subclassers should not
     * call this directly, but instead should call getJustifiedLayout, which
     * will call this method on a clone of this layout, preserving
     * the original.
     *
     * @param justificationWidth the width to use when justifying the line.
     * For best results, it should not be too different from the current
     * advance of the line.
     * @see #getJustifiedLayout(float)
     */
    protected void handleJustify(float justificationWidth) {
      // never called
    }


    /**
     * Returns the baseline for this <code>TextLayout</code>.
     * The baseline is one of the values defined in <code>Font</code>,
     * which are roman, centered and hanging.  Ascent and descent are
     * relative to this baseline.  The <code>baselineOffsets</code>
     * are also relative to this baseline.
     * @return the baseline of this <code>TextLayout</code>.
     * @see #getBaselineOffsets()
     * @see Font
     */
    public byte getBaseline() {
        return baseline;
    }

    /**
     * Returns the offsets array for the baselines used for this
     * <code>TextLayout</code>.
     * <p>
     * The array is indexed by one of the values defined in
     * <code>Font</code>, which are roman, centered and hanging.  The
     * values are relative to this <code>TextLayout</code> object's
     * baseline, so that <code>getBaselineOffsets[getBaseline()] == 0</code>.
     * Offsets are added to the position of the <code>TextLayout</code>
     * object's baseline to get the position for the new baseline.
     * @return the offsets array containing the baselines used for this
     *    <code>TextLayout</code>.
     * @see #getBaseline()
     * @see Font
     */
    public float[] getBaselineOffsets() {
        float[] offsets = new float[baselineOffsets.length];
        System.arraycopy(baselineOffsets, 0, offsets, 0, offsets.length);
        return offsets;
    }

    /**
     * Returns the advance of this <code>TextLayout</code>.
     * The advance is the distance from the origin to the advance of the
     * rightmost (bottommost) character.  This is in baseline-relative
     * coordinates.
     * @return the advance of this <code>TextLayout</code>.
     */
    public float getAdvance() {
        ensureCache();
        return lineMetrics.advance;
    }

    /**
     * Returns the advance of this <code>TextLayout</code>, minus trailing
     * whitespace.  This is in baseline-relative coordinates.
     * @return the advance of this <code>TextLayout</code> without the
     *      trailing whitespace.
     * @see #getAdvance()
     */
    public float getVisibleAdvance() {
        ensureCache();
        return visibleAdvance;
    }

    /**
     * Returns the ascent of this <code>TextLayout</code>.
     * The ascent is the distance from the top (right) of the
     * <code>TextLayout</code> to the baseline.  It is always either
     * positive or zero.  The ascent is sufficient to
     * accomodate superscripted text and is the maximum of the sum of the
     * ascent, offset, and baseline of each glyph.  The ascent is
     * the maximum ascent from the baseline of all the text in the
     * TextLayout.  It is in baseline-relative coordinates.
     * @return the ascent of this <code>TextLayout</code>.
     */
    public float getAscent() {
        ensureCache();
        return lineMetrics.ascent;
    }

    /**
     * Returns the descent of this <code>TextLayout</code>.
     * The descent is the distance from the baseline to the bottom (left) of
     * the <code>TextLayout</code>.  It is always either positive or zero.
     * The descent is sufficient to accomodate subscripted text and is the
     * maximum of the sum of the descent, offset, and baseline of each glyph.
     * This is the maximum descent from the baseline of all the text in
     * the TextLayout.  It is in baseline-relative coordinates.
     * @return the descent of this <code>TextLayout</code>.
     */
    public float getDescent() {
        ensureCache();
        return lineMetrics.descent;
    }

    /**
     * Returns the leading of the <code>TextLayout</code>.
     * The leading is the suggested interline spacing for this
     * <code>TextLayout</code>.  This is in baseline-relative
     * coordinates.
     * <p>
     * The leading is computed from the leading, descent, and baseline
     * of all glyphvectors in the <code>TextLayout</code>.  The algorithm
     * is roughly as follows:
     * <blockquote><pre>
     * maxD = 0;
     * maxDL = 0;
     * for (GlyphVector g in all glyphvectors) {
     *    maxD = max(maxD, g.getDescent() + offsets[g.getBaseline()]);
     *    maxDL = max(maxDL, g.getDescent() + g.getLeading() +
     *                       offsets[g.getBaseline()]);
     * }
     * return maxDL - maxD;
     * </pre></blockquote>
     * @return the leading of this <code>TextLayout</code>.
     */
    public float getLeading() {
        ensureCache();
        return lineMetrics.leading;
    }

    /**
     * Returns the bounds of this <code>TextLayout</code>.
     * The bounds are in standard coordinates.
     * <p>Due to rasterization effects, this bounds might not enclose all of the
     * pixels rendered by the TextLayout.</p>
     * It might not coincide exactly with the ascent, descent,
     * origin or advance of the <code>TextLayout</code>.
     * @return a {@link Rectangle2D} that is the bounds of this
     *        <code>TextLayout</code>.
     */
    public Rectangle2D getBounds() {
        ensureCache();

        if (boundsRect == null) {
            Rectangle2D vb = textLine.getVisualBounds();
            if (dx != 0 || dy != 0) {
                vb.setRect(vb.getX() - dx,
                           vb.getY() - dy,
                           vb.getWidth(),
                           vb.getHeight());
            }
            boundsRect = vb;
        }

        Rectangle2D bounds = new Rectangle2D.Float();
        bounds.setRect(boundsRect);

        return bounds;
    }

    /**
     * Returns the pixel bounds of this <code>TextLayout</code> when
     * rendered in a graphics with the given
     * <code>FontRenderContext</code> at the given location.  The
     * graphics render context need not be the same as the
     * <code>FontRenderContext</code> used to create this
     * <code>TextLayout</code>, and can be null.  If it is null, the
     * <code>FontRenderContext</code> of this <code>TextLayout</code>
     * is used.
     * @param frc the <code>FontRenderContext</code> of the <code>Graphics</code>.
     * @param x the x-coordinate at which to render this <code>TextLayout</code>.
     * @param y the y-coordinate at which to render this <code>TextLayout</code>.
     * @return a <code>Rectangle</code> bounding the pixels that would be affected.
     * @see GlyphVector#getPixelBounds
     * @since 1.6
     */
    public Rectangle getPixelBounds(FontRenderContext frc, float x, float y) {
        return textLine.getPixelBounds(frc, x, y);
    }

    /**
     * Returns <code>true</code> if this <code>TextLayout</code> has
     * a left-to-right base direction or <code>false</code> if it has
     * a right-to-left base direction.  The <code>TextLayout</code>
     * has a base direction of either left-to-right (LTR) or
     * right-to-left (RTL).  The base direction is independent of the
     * actual direction of text on the line, which may be either LTR,
     * RTL, or mixed. Left-to-right layouts by default should position
     * flush left.  If the layout is on a tabbed line, the
     * tabs run left to right, so that logically successive layouts position
     * left to right.  The opposite is true for RTL layouts. By default they
     * should position flush left, and tabs run right-to-left.
     * @return <code>true</code> if the base direction of this
     *         <code>TextLayout</code> is left-to-right; <code>false</code>
     *         otherwise.
     */
    public boolean isLeftToRight() {
        return textLine.isDirectionLTR();
    }

    /**
     * Returns <code>true</code> if this <code>TextLayout</code> is vertical.
     * @return <code>true</code> if this <code>TextLayout</code> is vertical;
     *      <code>false</code> otherwise.
     */
    public boolean isVertical() {
        return isVerticalLine;
    }

    /**
     * Returns the number of characters represented by this
     * <code>TextLayout</code>.
     * @return the number of characters in this <code>TextLayout</code>.
     */
    public int getCharacterCount() {
        return characterCount;
    }

    /*
     * carets and hit testing
     *
     * Positions on a text line are represented by instances of TextHitInfo.
     * Any TextHitInfo with characterOffset between 0 and characterCount-1,
     * inclusive, represents a valid position on the line.  Additionally,
     * [-1, trailing] and [characterCount, leading] are valid positions, and
     * represent positions at the logical start and end of the line,
     * respectively.
     *
     * The characterOffsets in TextHitInfo's used and returned by TextLayout
     * are relative to the beginning of the text layout, not necessarily to
     * the beginning of the text storage the client is using.
     *
     *
     * Every valid TextHitInfo has either one or two carets associated with it.
     * A caret is a visual location in the TextLayout indicating where text at
     * the TextHitInfo will be displayed on screen.  If a TextHitInfo
     * represents a location on a directional boundary, then there are two
     * possible visible positions for newly inserted text.  Consider the
     * following example, in which capital letters indicate right-to-left text,
     * and the overall line direction is left-to-right:
     *
     * Text Storage: [ a, b, C, D, E, f ]
     * Display:        a b E D C f
     *
     * The text hit info (1, t) represents the trailing side of 'b'.  If 'q',
     * a left-to-right character is inserted into the text storage at this
     * location, it will be displayed between the 'b' and the 'E':
     *
     * Text Storage: [ a, b, q, C, D, E, f ]
     * Display:        a b q E D C f
     *
     * However, if a 'W', which is right-to-left, is inserted into the storage
     * after 'b', the storage and display will be:
     *
     * Text Storage: [ a, b, W, C, D, E, f ]
     * Display:        a b E D C W f
     *
     * So, for the original text storage, two carets should be displayed for
     * location (1, t): one visually between 'b' and 'E' and one visually
     * between 'C' and 'f'.
     *
     *
     * When two carets are displayed for a TextHitInfo, one caret is the
     * 'strong' caret and the other is the 'weak' caret.  The strong caret
     * indicates where an inserted character will be displayed when that
     * character's direction is the same as the direction of the TextLayout.
     * The weak caret shows where an character inserted character will be
     * displayed when the character's direction is opposite that of the
     * TextLayout.
     *
     *
     * Clients should not be overly concerned with the details of correct
     * caret display. TextLayout.getCaretShapes(TextHitInfo) will return an
     * array of two paths representing where carets should be displayed.
     * The first path in the array is the strong caret; the second element,
     * if non-null, is the weak caret.  If the second element is null,
     * then there is no weak caret for the given TextHitInfo.
     *
     *
     * Since text can be visually reordered, logically consecutive
     * TextHitInfo's may not be visually consecutive.  One implication of this
     * is that a client cannot tell from inspecting a TextHitInfo whether the
     * hit represents the first (or last) caret in the layout.  Clients
     * can call getVisualOtherHit();  if the visual companion is
     * (-1, TRAILING) or (characterCount, LEADING), then the hit is at the
     * first (last) caret position in the layout.
     */

    private float[] getCaretInfo(int caret,
                                 Rectangle2D bounds,
                                 float[] info) {

        float top1X, top2X;
        float bottom1X, bottom2X;

        if (caret == 0 || caret == characterCount) {

            float pos;
            int logIndex;
            if (caret == characterCount) {
                logIndex = textLine.visualToLogical(characterCount-1);
                pos = textLine.getCharLinePosition(logIndex)
                                        + textLine.getCharAdvance(logIndex);
            }
            else {
                logIndex = textLine.visualToLogical(caret);
                pos = textLine.getCharLinePosition(logIndex);
            }
            float angle = textLine.getCharAngle(logIndex);
            float shift = textLine.getCharShift(logIndex);
            pos += angle * shift;
            top1X = top2X = pos + angle*textLine.getCharAscent(logIndex);
            bottom1X = bottom2X = pos - angle*textLine.getCharDescent(logIndex);
        }
        else {

            {
                int logIndex = textLine.visualToLogical(caret-1);
                float angle1 = textLine.getCharAngle(logIndex);
                float pos1 = textLine.getCharLinePosition(logIndex)
                                    + textLine.getCharAdvance(logIndex);
                if (angle1 != 0) {
                    pos1 += angle1 * textLine.getCharShift(logIndex);
                    top1X = pos1 + angle1*textLine.getCharAscent(logIndex);
                    bottom1X = pos1 - angle1*textLine.getCharDescent(logIndex);
                }
                else {
                    top1X = bottom1X = pos1;
                }
            }
            {
                int logIndex = textLine.visualToLogical(caret);
                float angle2 = textLine.getCharAngle(logIndex);
                float pos2 = textLine.getCharLinePosition(logIndex);
                if (angle2 != 0) {
                    pos2 += angle2*textLine.getCharShift(logIndex);
                    top2X = pos2 + angle2*textLine.getCharAscent(logIndex);
                    bottom2X = pos2 - angle2*textLine.getCharDescent(logIndex);
                }
                else {
                    top2X = bottom2X = pos2;
                }
            }
        }

        float topX = (top1X + top2X) / 2;
        float bottomX = (bottom1X + bottom2X) / 2;

        if (info == null) {
            info = new float[2];
        }

        if (isVerticalLine) {
            info[1] = (float) ((topX - bottomX) / bounds.getWidth());
            info[0] = (float) (topX + (info[1]*bounds.getX()));
        }
        else {
            info[1] = (float) ((topX - bottomX) / bounds.getHeight());
            info[0] = (float) (bottomX + (info[1]*bounds.getMaxY()));
        }

        return info;
    }

    /**
     * Returns information about the caret corresponding to <code>hit</code>.
     * The first element of the array is the intersection of the caret with
     * the baseline, as a distance along the baseline. The second element
     * of the array is the inverse slope (run/rise) of the caret, measured
     * with respect to the baseline at that point.
     * <p>
     * This method is meant for informational use.  To display carets, it
     * is better to use <code>getCaretShapes</code>.
     * @param hit a hit on a character in this <code>TextLayout</code>
     * @param bounds the bounds to which the caret info is constructed.
     *     The bounds is in baseline-relative coordinates.
     * @return a two-element array containing the position and slope of
     * the caret.  The returned caret info is in baseline-relative coordinates.
     * @see #getCaretShapes(int, Rectangle2D, TextLayout.CaretPolicy)
     * @see Font#getItalicAngle
     */
    public float[] getCaretInfo(TextHitInfo hit, Rectangle2D bounds) {
        ensureCache();
        checkTextHit(hit);

        return getCaretInfoTestInternal(hit, bounds);
    }

    // this version provides extra info in the float array
    // the first two values are as above
    // the next four values are the endpoints of the caret, as computed
    // using the hit character's offset (baseline + ssoffset) and
    // natural ascent and descent.
    // these  values are trimmed to the bounds where required to fit,
    // but otherwise independent of it.
    private float[] getCaretInfoTestInternal(TextHitInfo hit, Rectangle2D bounds) {
        ensureCache();
        checkTextHit(hit);

        float[] info = new float[6];

        // get old data first
        getCaretInfo(hitToCaret(hit), bounds, info);

        // then add our new data
        double iangle, ixbase, p1x, p1y, p2x, p2y;

        int charix = hit.getCharIndex();
        boolean lead = hit.isLeadingEdge();
        boolean ltr = textLine.isDirectionLTR();
        boolean horiz = !isVertical();

        if (charix == -1 || charix == characterCount) {
            // !!! note: want non-shifted, baseline ascent and descent here!
            // TextLine should return appropriate line metrics object for these values
            TextLineMetrics m = textLine.getMetrics();
            boolean low = ltr == (charix == -1);
            iangle = 0;
            if (horiz) {
                p1x = p2x = low ? 0 : m.advance;
                p1y = -m.ascent;
                p2y = m.descent;
            } else {
                p1y = p2y = low ? 0 : m.advance;
                p1x = m.descent;
                p2x = m.ascent;
            }
        } else {
            CoreMetrics thiscm = textLine.getCoreMetricsAt(charix);
            iangle = thiscm.italicAngle;
            ixbase = textLine.getCharLinePosition(charix, lead);
            if (thiscm.baselineIndex < 0) {
                // this is a graphic, no italics, use entire line height for caret
                TextLineMetrics m = textLine.getMetrics();
                if (horiz) {
                    p1x = p2x = ixbase;
                    if (thiscm.baselineIndex == GraphicAttribute.TOP_ALIGNMENT) {
                        p1y = -m.ascent;
                        p2y = p1y + thiscm.height;
                    } else {
                        p2y = m.descent;
                        p1y = p2y - thiscm.height;
                    }
                } else {
                    p1y = p2y = ixbase;
                    p1x = m.descent;
                    p2x = m.ascent;
                    // !!! top/bottom adjustment not implemented for vertical
                }
            } else {
                float bo = baselineOffsets[thiscm.baselineIndex];
                if (horiz) {
                    ixbase += iangle * thiscm.ssOffset;
                    p1x = ixbase + iangle * thiscm.ascent;
                    p2x = ixbase - iangle * thiscm.descent;
                    p1y = bo - thiscm.ascent;
                    p2y = bo + thiscm.descent;
                } else {
                    ixbase -= iangle * thiscm.ssOffset;
                    p1y = ixbase + iangle * thiscm.ascent;
                    p2y = ixbase - iangle * thiscm.descent;
                    p1x = bo + thiscm.ascent;
                    p2x = bo + thiscm.descent;
                }
            }
        }

        info[2] = (float)p1x;
        info[3] = (float)p1y;
        info[4] = (float)p2x;
        info[5] = (float)p2y;

        return info;
    }

    /**
     * Returns information about the caret corresponding to <code>hit</code>.
     * This method is a convenience overload of <code>getCaretInfo</code> and
     * uses the natural bounds of this <code>TextLayout</code>.
     * @param hit a hit on a character in this <code>TextLayout</code>
     * @return the information about a caret corresponding to a hit.  The
     *     returned caret info is in baseline-relative coordinates.
     */
    public float[] getCaretInfo(TextHitInfo hit) {

        return getCaretInfo(hit, getNaturalBounds());
    }

    /**
     * Returns a caret index corresponding to <code>hit</code>.
     * Carets are numbered from left to right (top to bottom) starting from
     * zero. This always places carets next to the character hit, on the
     * indicated side of the character.
     * @param hit a hit on a character in this <code>TextLayout</code>
     * @return a caret index corresponding to the specified hit.
     */
    private int hitToCaret(TextHitInfo hit) {

        int hitIndex = hit.getCharIndex();

        if (hitIndex < 0) {
            return textLine.isDirectionLTR() ? 0 : characterCount;
        } else if (hitIndex >= characterCount) {
            return textLine.isDirectionLTR() ? characterCount : 0;
        }

        int visIndex = textLine.logicalToVisual(hitIndex);

        if (hit.isLeadingEdge() != textLine.isCharLTR(hitIndex)) {
            ++visIndex;
        }

        return visIndex;
    }

    /**
     * Given a caret index, return a hit whose caret is at the index.
     * The hit is NOT guaranteed to be strong!!!
     *
     * @param caret a caret index.
     * @return a hit on this layout whose strong caret is at the requested
     * index.
     */
    private TextHitInfo caretToHit(int caret) {

        if (caret == 0 || caret == characterCount) {

            if ((caret == characterCount) == textLine.isDirectionLTR()) {
                return TextHitInfo.leading(characterCount);
            }
            else {
                return TextHitInfo.trailing(-1);
            }
        }
        else {

            int charIndex = textLine.visualToLogical(caret);
            boolean leading = textLine.isCharLTR(charIndex);

            return leading? TextHitInfo.leading(charIndex)
                            : TextHitInfo.trailing(charIndex);
        }
    }

    private boolean caretIsValid(int caret) {

        if (caret == characterCount || caret == 0) {
            return true;
        }

        int offset = textLine.visualToLogical(caret);

        if (!textLine.isCharLTR(offset)) {
            offset = textLine.visualToLogical(caret-1);
            if (textLine.isCharLTR(offset)) {
                return true;
            }
        }

        // At this point, the leading edge of the character
        // at offset is at the given caret.

        return textLine.caretAtOffsetIsValid(offset);
    }

    /**
     * Returns the hit for the next caret to the right (bottom); if there
     * is no such hit, returns <code>null</code>.
     * If the hit character index is out of bounds, an
     * {@link IllegalArgumentException} is thrown.
     * @param hit a hit on a character in this layout
     * @return a hit whose caret appears at the next position to the
     * right (bottom) of the caret of the provided hit or <code>null</code>.
     */
    public TextHitInfo getNextRightHit(TextHitInfo hit) {
        ensureCache();
        checkTextHit(hit);

        int caret = hitToCaret(hit);

        if (caret == characterCount) {
            return null;
        }

        do {
            ++caret;
        } while (!caretIsValid(caret));

        return caretToHit(caret);
    }

    /**
     * Returns the hit for the next caret to the right (bottom); if no
     * such hit, returns <code>null</code>.  The hit is to the right of
     * the strong caret at the specified offset, as determined by the
     * specified policy.
     * The returned hit is the stronger of the two possible
     * hits, as determined by the specified policy.
     * @param offset an insertion offset in this <code>TextLayout</code>.
     * Cannot be less than 0 or greater than this <code>TextLayout</code>
     * object's character count.
     * @param policy the policy used to select the strong caret
     * @return a hit whose caret appears at the next position to the
     * right (bottom) of the caret of the provided hit, or <code>null</code>.
     */
    public TextHitInfo getNextRightHit(int offset, CaretPolicy policy) {

        if (offset < 0 || offset > characterCount) {
            throw new IllegalArgumentException("Offset out of bounds in TextLayout.getNextRightHit()");
        }

        if (policy == null) {
            throw new IllegalArgumentException("Null CaretPolicy passed to TextLayout.getNextRightHit()");
        }

        TextHitInfo hit1 = TextHitInfo.afterOffset(offset);
        TextHitInfo hit2 = hit1.getOtherHit();

        TextHitInfo nextHit = getNextRightHit(policy.getStrongCaret(hit1, hit2, this));

        if (nextHit != null) {
            TextHitInfo otherHit = getVisualOtherHit(nextHit);
            return policy.getStrongCaret(otherHit, nextHit, this);
        }
        else {
            return null;
        }
    }

    /**
     * Returns the hit for the next caret to the right (bottom); if no
     * such hit, returns <code>null</code>.  The hit is to the right of
     * the strong caret at the specified offset, as determined by the
     * default policy.
     * The returned hit is the stronger of the two possible
     * hits, as determined by the default policy.
     * @param offset an insertion offset in this <code>TextLayout</code>.
     * Cannot be less than 0 or greater than the <code>TextLayout</code>
     * object's character count.
     * @return a hit whose caret appears at the next position to the
     * right (bottom) of the caret of the provided hit, or <code>null</code>.
     */
    public TextHitInfo getNextRightHit(int offset) {

        return getNextRightHit(offset, DEFAULT_CARET_POLICY);
    }

    /**
     * Returns the hit for the next caret to the left (top); if no such
     * hit, returns <code>null</code>.
     * If the hit character index is out of bounds, an
     * <code>IllegalArgumentException</code> is thrown.
     * @param hit a hit on a character in this <code>TextLayout</code>.
     * @return a hit whose caret appears at the next position to the
     * left (top) of the caret of the provided hit, or <code>null</code>.
     */
    public TextHitInfo getNextLeftHit(TextHitInfo hit) {
        ensureCache();
        checkTextHit(hit);

        int caret = hitToCaret(hit);

        if (caret == 0) {
            return null;
        }

        do {
            --caret;
        } while(!caretIsValid(caret));

        return caretToHit(caret);
    }

    /**
     * Returns the hit for the next caret to the left (top); if no
     * such hit, returns <code>null</code>.  The hit is to the left of
     * the strong caret at the specified offset, as determined by the
     * specified policy.
     * The returned hit is the stronger of the two possible
     * hits, as determined by the specified policy.
     * @param offset an insertion offset in this <code>TextLayout</code>.
     * Cannot be less than 0 or greater than this <code>TextLayout</code>
     * object's character count.
     * @param policy the policy used to select the strong caret
     * @return a hit whose caret appears at the next position to the
     * left (top) of the caret of the provided hit, or <code>null</code>.
     */
    public TextHitInfo getNextLeftHit(int offset, CaretPolicy policy) {

        if (policy == null) {
            throw new IllegalArgumentException("Null CaretPolicy passed to TextLayout.getNextLeftHit()");
        }

        if (offset < 0 || offset > characterCount) {
            throw new IllegalArgumentException("Offset out of bounds in TextLayout.getNextLeftHit()");
        }

        TextHitInfo hit1 = TextHitInfo.afterOffset(offset);
        TextHitInfo hit2 = hit1.getOtherHit();

        TextHitInfo nextHit = getNextLeftHit(policy.getStrongCaret(hit1, hit2, this));

        if (nextHit != null) {
            TextHitInfo otherHit = getVisualOtherHit(nextHit);
            return policy.getStrongCaret(otherHit, nextHit, this);
        }
        else {
            return null;
        }
    }

    /**
     * Returns the hit for the next caret to the left (top); if no
     * such hit, returns <code>null</code>.  The hit is to the left of
     * the strong caret at the specified offset, as determined by the
     * default policy.
     * The returned hit is the stronger of the two possible
     * hits, as determined by the default policy.
     * @param offset an insertion offset in this <code>TextLayout</code>.
     * Cannot be less than 0 or greater than this <code>TextLayout</code>
     * object's character count.
     * @return a hit whose caret appears at the next position to the
     * left (top) of the caret of the provided hit, or <code>null</code>.
     */
    public TextHitInfo getNextLeftHit(int offset) {

        return getNextLeftHit(offset, DEFAULT_CARET_POLICY);
    }

    /**
     * Returns the hit on the opposite side of the specified hit's caret.
     * @param hit the specified hit
     * @return a hit that is on the opposite side of the specified hit's
     *    caret.
     */
    public TextHitInfo getVisualOtherHit(TextHitInfo hit) {

        ensureCache();
        checkTextHit(hit);

        int hitCharIndex = hit.getCharIndex();

        int charIndex;
        boolean leading;

        if (hitCharIndex == -1 || hitCharIndex == characterCount) {

            int visIndex;
            if (textLine.isDirectionLTR() == (hitCharIndex == -1)) {
                visIndex = 0;
            }
            else {
                visIndex = characterCount-1;
            }

            charIndex = textLine.visualToLogical(visIndex);

            if (textLine.isDirectionLTR() == (hitCharIndex == -1)) {
                // at left end
                leading = textLine.isCharLTR(charIndex);
            }
            else {
                // at right end
                leading = !textLine.isCharLTR(charIndex);
            }
        }
        else {

            int visIndex = textLine.logicalToVisual(hitCharIndex);

            boolean movedToRight;
            if (textLine.isCharLTR(hitCharIndex) == hit.isLeadingEdge()) {
                --visIndex;
                movedToRight = false;
            }
            else {
                ++visIndex;
                movedToRight = true;
            }

            if (visIndex > -1 && visIndex < characterCount) {
                charIndex = textLine.visualToLogical(visIndex);
                leading = movedToRight == textLine.isCharLTR(charIndex);
            }
            else {
                charIndex =
                    (movedToRight == textLine.isDirectionLTR())? characterCount : -1;
                leading = charIndex == characterCount;
            }
        }

        return leading? TextHitInfo.leading(charIndex) :
                                TextHitInfo.trailing(charIndex);
    }

    private double[] getCaretPath(TextHitInfo hit, Rectangle2D bounds) {
        float[] info = getCaretInfo(hit, bounds);
        return new double[] { info[2], info[3], info[4], info[5] };
    }

    /**
     * Return an array of four floats corresponding the endpoints of the caret
     * x0, y0, x1, y1.
     *
     * This creates a line along the slope of the caret intersecting the
     * baseline at the caret
     * position, and extending from ascent above the baseline to descent below
     * it.
     */
    private double[] getCaretPath(int caret, Rectangle2D bounds,
                                  boolean clipToBounds) {

        float[] info = getCaretInfo(caret, bounds, null);

        double pos = info[0];
        double slope = info[1];

        double x0, y0, x1, y1;
        double x2 = -3141.59, y2 = -2.7; // values are there to make compiler happy

        double left = bounds.getX();
        double right = left + bounds.getWidth();
        double top = bounds.getY();
        double bottom = top + bounds.getHeight();

        boolean threePoints = false;

        if (isVerticalLine) {

            if (slope >= 0) {
                x0 = left;
                x1 = right;
            }
            else {
                x1 = left;
                x0 = right;
            }

            y0 = pos + x0 * slope;
            y1 = pos + x1 * slope;

            // y0 <= y1, always

            if (clipToBounds) {
                if (y0 < top) {
                    if (slope <= 0 || y1 <= top) {
                        y0 = y1 = top;
                    }
                    else {
                        threePoints = true;
                        y0 = top;
                        y2 = top;
                        x2 = x1 + (top-y1)/slope;
                        if (y1 > bottom) {
                            y1 = bottom;
                        }
                    }
                }
                else if (y1 > bottom) {
                    if (slope >= 0 || y0 >= bottom) {
                        y0 = y1 = bottom;
                    }
                    else {
                        threePoints = true;
                        y1 = bottom;
                        y2 = bottom;
                        x2 = x0 + (bottom-x1)/slope;
                    }
                }
            }

        }
        else {

            if (slope >= 0) {
                y0 = bottom;
                y1 = top;
            }
            else {
                y1 = bottom;
                y0 = top;
            }

            x0 = pos - y0 * slope;
            x1 = pos - y1 * slope;

            // x0 <= x1, always

            if (clipToBounds) {
                if (x0 < left) {
                    if (slope <= 0 || x1 <= left) {
                        x0 = x1 = left;
                    }
                    else {
                        threePoints = true;
                        x0 = left;
                        x2 = left;
                        y2 = y1 - (left-x1)/slope;
                        if (x1 > right) {
                            x1 = right;
                        }
                    }
                }
                else if (x1 > right) {
                    if (slope >= 0 || x0 >= right) {
                        x0 = x1 = right;
                    }
                    else {
                        threePoints = true;
                        x1 = right;
                        x2 = right;
                        y2 = y0 - (right-x0)/slope;
                    }
                }
            }
        }

        return threePoints?
                    new double[] { x0, y0, x2, y2, x1, y1 } :
                    new double[] { x0, y0, x1, y1 };
    }


    private static GeneralPath pathToShape(double[] path, boolean close, LayoutPathImpl lp) {
        GeneralPath result = new GeneralPath(GeneralPath.WIND_EVEN_ODD, path.length);
        result.moveTo((float)path[0], (float)path[1]);
        for (int i = 2; i < path.length; i += 2) {
            result.lineTo((float)path[i], (float)path[i+1]);
        }
        if (close) {
            result.closePath();
        }

        if (lp != null) {
            result = (GeneralPath)lp.mapShape(result);
        }
        return result;
    }

    /**
     * Returns a {@link Shape} representing the caret at the specified
     * hit inside the specified bounds.
     * @param hit the hit at which to generate the caret
     * @param bounds the bounds of the <code>TextLayout</code> to use
     *    in generating the caret.  The bounds is in baseline-relative
     *    coordinates.
     * @return a <code>Shape</code> representing the caret.  The returned
     *    shape is in standard coordinates.
     */
    public Shape getCaretShape(TextHitInfo hit, Rectangle2D bounds) {
        ensureCache();
        checkTextHit(hit);

        if (bounds == null) {
            throw new IllegalArgumentException("Null Rectangle2D passed to TextLayout.getCaret()");
        }

        return pathToShape(getCaretPath(hit, bounds), false, textLine.getLayoutPath());
    }

    /**
     * Returns a <code>Shape</code> representing the caret at the specified
     * hit inside the natural bounds of this <code>TextLayout</code>.
     * @param hit the hit at which to generate the caret
     * @return a <code>Shape</code> representing the caret.  The returned
     *     shape is in standard coordinates.
     */
    public Shape getCaretShape(TextHitInfo hit) {

        return getCaretShape(hit, getNaturalBounds());
    }

    /**
     * Return the "stronger" of the TextHitInfos.  The TextHitInfos
     * should be logical or visual counterparts.  They are not
     * checked for validity.
     */
    private final TextHitInfo getStrongHit(TextHitInfo hit1, TextHitInfo hit2) {

        // right now we're using the following rule for strong hits:
        // A hit on a character with a lower level
        // is stronger than one on a character with a higher level.
        // If this rule ties, the hit on the leading edge of a character wins.
        // If THIS rule ties, hit1 wins.  Both rules shouldn't tie, unless the
        // infos aren't counterparts of some sort.

        byte hit1Level = getCharacterLevel(hit1.getCharIndex());
        byte hit2Level = getCharacterLevel(hit2.getCharIndex());

        if (hit1Level == hit2Level) {
            if (hit2.isLeadingEdge() && !hit1.isLeadingEdge()) {
                return hit2;
            }
            else {
                return hit1;
            }
        }
        else {
            return (hit1Level < hit2Level)? hit1 : hit2;
        }
    }

    /**
     * Returns the level of the character at <code>index</code>.
     * Indices -1 and <code>characterCount</code> are assigned the base
     * level of this <code>TextLayout</code>.
     * @param index the index of the character from which to get the level
     * @return the level of the character at the specified index.
     */
    public byte getCharacterLevel(int index) {

        // hmm, allow indices at endpoints?  For now, yes.
        if (index < -1 || index > characterCount) {
            throw new IllegalArgumentException("Index is out of range in getCharacterLevel.");
        }

        ensureCache();
        if (index == -1 || index == characterCount) {
             return (byte) (textLine.isDirectionLTR()? 0 : 1);
        }

        return textLine.getCharLevel(index);
    }

    /**
     * Returns two paths corresponding to the strong and weak caret.
     * @param offset an offset in this <code>TextLayout</code>
     * @param bounds the bounds to which to extend the carets.  The
     * bounds is in baseline-relative coordinates.
     * @param policy the specified <code>CaretPolicy</code>
     * @return an array of two paths.  Element zero is the strong
     * caret.  If there are two carets, element one is the weak caret,
     * otherwise it is <code>null</code>. The returned shapes
     * are in standard coordinates.
     */
    public Shape[] getCaretShapes(int offset, Rectangle2D bounds, CaretPolicy policy) {

        ensureCache();

        if (offset < 0 || offset > characterCount) {
            throw new IllegalArgumentException("Offset out of bounds in TextLayout.getCaretShapes()");
        }

        if (bounds == null) {
            throw new IllegalArgumentException("Null Rectangle2D passed to TextLayout.getCaretShapes()");
        }

        if (policy == null) {
            throw new IllegalArgumentException("Null CaretPolicy passed to TextLayout.getCaretShapes()");
        }

        Shape[] result = new Shape[2];

        TextHitInfo hit = TextHitInfo.afterOffset(offset);

        int hitCaret = hitToCaret(hit);

        LayoutPathImpl lp = textLine.getLayoutPath();
        Shape hitShape = pathToShape(getCaretPath(hit, bounds), false, lp);
        TextHitInfo otherHit = hit.getOtherHit();
        int otherCaret = hitToCaret(otherHit);

        if (hitCaret == otherCaret) {
            result[0] = hitShape;
        }
        else { // more than one caret
            Shape otherShape = pathToShape(getCaretPath(otherHit, bounds), false, lp);

            TextHitInfo strongHit = policy.getStrongCaret(hit, otherHit, this);
            boolean hitIsStrong = strongHit.equals(hit);

            if (hitIsStrong) {// then other is weak
                result[0] = hitShape;
                result[1] = otherShape;
            }
            else {
                result[0] = otherShape;
                result[1] = hitShape;
            }
        }

        return result;
    }

    /**
     * Returns two paths corresponding to the strong and weak caret.
     * This method is a convenience overload of <code>getCaretShapes</code>
     * that uses the default caret policy.
     * @param offset an offset in this <code>TextLayout</code>
     * @param bounds the bounds to which to extend the carets.  This is
     *     in baseline-relative coordinates.
     * @return two paths corresponding to the strong and weak caret as
     *    defined by the <code>DEFAULT_CARET_POLICY</code>.  These are
     *    in standard coordinates.
     */
    public Shape[] getCaretShapes(int offset, Rectangle2D bounds) {
        // {sfb} parameter checking is done in overloaded version
        return getCaretShapes(offset, bounds, DEFAULT_CARET_POLICY);
    }

    /**
     * Returns two paths corresponding to the strong and weak caret.
     * This method is a convenience overload of <code>getCaretShapes</code>
     * that uses the default caret policy and this <code>TextLayout</code>
     * object's natural bounds.
     * @param offset an offset in this <code>TextLayout</code>
     * @return two paths corresponding to the strong and weak caret as
     *    defined by the <code>DEFAULT_CARET_POLICY</code>.  These are
     *    in standard coordinates.
     */
    public Shape[] getCaretShapes(int offset) {
        // {sfb} parameter checking is done in overloaded version
        return getCaretShapes(offset, getNaturalBounds(), DEFAULT_CARET_POLICY);
    }

    // A utility to return a path enclosing the given path
    // Path0 must be left or top of path1
    // {jbr} no assumptions about size of path0, path1 anymore.
    private GeneralPath boundingShape(double[] path0, double[] path1) {

        // Really, we want the path to be a convex hull around all of the
        // points in path0 and path1.  But we can get by with less than
        // that.  We do need to prevent the two segments which
        // join path0 to path1 from crossing each other.  So, if we
        // traverse path0 from top to bottom, we'll traverse path1 from
        // bottom to top (and vice versa).

        GeneralPath result = pathToShape(path0, false, null);

        boolean sameDirection;

        if (isVerticalLine) {
            sameDirection = (path0[1] > path0[path0.length-1]) ==
                            (path1[1] > path1[path1.length-1]);
        }
        else {
            sameDirection = (path0[0] > path0[path0.length-2]) ==
                            (path1[0] > path1[path1.length-2]);
        }

        int start;
        int limit;
        int increment;

        if (sameDirection) {
            start = path1.length-2;
            limit = -2;
            increment = -2;
        }
        else {
            start = 0;
            limit = path1.length;
            increment = 2;
        }

        for (int i = start; i != limit; i += increment) {
            result.lineTo((float)path1[i], (float)path1[i+1]);
        }

        result.closePath();

        return result;
    }

    // A utility to convert a pair of carets into a bounding path
    // {jbr} Shape is never outside of bounds.
    private GeneralPath caretBoundingShape(int caret0,
                                           int caret1,
                                           Rectangle2D bounds) {

        if (caret0 > caret1) {
            int temp = caret0;
            caret0 = caret1;
            caret1 = temp;
        }

        return boundingShape(getCaretPath(caret0, bounds, true),
                             getCaretPath(caret1, bounds, true));
    }

    /*
     * A utility to return the path bounding the area to the left (top) of the
     * layout.
     * Shape is never outside of bounds.
     */
    private GeneralPath leftShape(Rectangle2D bounds) {

        double[] path0;
        if (isVerticalLine) {
            path0 = new double[] { bounds.getX(), bounds.getY(),
                                       bounds.getX() + bounds.getWidth(),
                                       bounds.getY() };
        } else {
            path0 = new double[] { bounds.getX(),
                                       bounds.getY() + bounds.getHeight(),
                                       bounds.getX(), bounds.getY() };
        }

        double[] path1 = getCaretPath(0, bounds, true);

        return boundingShape(path0, path1);
    }

    /*
     * A utility to return the path bounding the area to the right (bottom) of
     * the layout.
     */
    private GeneralPath rightShape(Rectangle2D bounds) {
        double[] path1;
        if (isVerticalLine) {
            path1 = new double[] {
                bounds.getX(),
                bounds.getY() + bounds.getHeight(),
                bounds.getX() + bounds.getWidth(),
                bounds.getY() + bounds.getHeight()
            };
        } else {
            path1 = new double[] {
                bounds.getX() + bounds.getWidth(),
                bounds.getY() + bounds.getHeight(),
                bounds.getX() + bounds.getWidth(),
                bounds.getY()
            };
        }

        double[] path0 = getCaretPath(characterCount, bounds, true);

        return boundingShape(path0, path1);
    }

    /**
     * Returns the logical ranges of text corresponding to a visual selection.
     * @param firstEndpoint an endpoint of the visual range
     * @param secondEndpoint the other endpoint of the visual range.
     * This endpoint can be less than <code>firstEndpoint</code>.
     * @return an array of integers representing start/limit pairs for the
     * selected ranges.
     * @see #getVisualHighlightShape(TextHitInfo, TextHitInfo, Rectangle2D)
     */
    public int[] getLogicalRangesForVisualSelection(TextHitInfo firstEndpoint,
                                                    TextHitInfo secondEndpoint) {
        ensureCache();

        checkTextHit(firstEndpoint);
        checkTextHit(secondEndpoint);

        // !!! probably want to optimize for all LTR text

        boolean[] included = new boolean[characterCount];

        int startIndex = hitToCaret(firstEndpoint);
        int limitIndex = hitToCaret(secondEndpoint);

        if (startIndex > limitIndex) {
            int t = startIndex;
            startIndex = limitIndex;
            limitIndex = t;
        }

        /*
         * now we have the visual indexes of the glyphs at the start and limit
         * of the selection range walk through runs marking characters that
         * were included in the visual range there is probably a more efficient
         * way to do this, but this ought to work, so hey
         */

        if (startIndex < limitIndex) {
            int visIndex = startIndex;
            while (visIndex < limitIndex) {
                included[textLine.visualToLogical(visIndex)] = true;
                ++visIndex;
            }
        }

        /*
         * count how many runs we have, ought to be one or two, but perhaps
         * things are especially weird
         */
        int count = 0;
        boolean inrun = false;
        for (int i = 0; i < characterCount; i++) {
            if (included[i] != inrun) {
                inrun = !inrun;
                if (inrun) {
                    count++;
                }
            }
        }

        int[] ranges = new int[count * 2];
        count = 0;
        inrun = false;
        for (int i = 0; i < characterCount; i++) {
            if (included[i] != inrun) {
                ranges[count++] = i;
                inrun = !inrun;
            }
        }
        if (inrun) {
            ranges[count++] = characterCount;
        }

        return ranges;
    }

    /**
     * Returns a path enclosing the visual selection in the specified range,
     * extended to <code>bounds</code>.
     * <p>
     * If the selection includes the leftmost (topmost) position, the selection
     * is extended to the left (top) of <code>bounds</code>.  If the
     * selection includes the rightmost (bottommost) position, the selection
     * is extended to the right (bottom) of the bounds.  The height
     * (width on vertical lines) of the selection is always extended to
     * <code>bounds</code>.
     * <p>
     * Although the selection is always contiguous, the logically selected
     * text can be discontiguous on lines with mixed-direction text.  The
     * logical ranges of text selected can be retrieved using
     * <code>getLogicalRangesForVisualSelection</code>.  For example,
     * consider the text 'ABCdef' where capital letters indicate
     * right-to-left text, rendered on a right-to-left line, with a visual
     * selection from 0L (the leading edge of 'A') to 3T (the trailing edge
     * of 'd').  The text appears as follows, with bold underlined areas
     * representing the selection:
     * <br><pre>
     *    d<u><b>efCBA  </b></u>
     * </pre>
     * The logical selection ranges are 0-3, 4-6 (ABC, ef) because the
     * visually contiguous text is logically discontiguous.  Also note that
     * since the rightmost position on the layout (to the right of 'A') is
     * selected, the selection is extended to the right of the bounds.
     * @param firstEndpoint one end of the visual selection
     * @param secondEndpoint the other end of the visual selection
     * @param bounds the bounding rectangle to which to extend the selection.
     *     This is in baseline-relative coordinates.
     * @return a <code>Shape</code> enclosing the selection.  This is in
     *     standard coordinates.
     * @see #getLogicalRangesForVisualSelection(TextHitInfo, TextHitInfo)
     * @see #getLogicalHighlightShape(int, int, Rectangle2D)
     */
    public Shape getVisualHighlightShape(TextHitInfo firstEndpoint,
                                        TextHitInfo secondEndpoint,
                                        Rectangle2D bounds)
    {
        ensureCache();

        checkTextHit(firstEndpoint);
        checkTextHit(secondEndpoint);

        if(bounds == null) {
                throw new IllegalArgumentException("Null Rectangle2D passed to TextLayout.getVisualHighlightShape()");
        }

        GeneralPath result = new GeneralPath(GeneralPath.WIND_EVEN_ODD);

        int firstCaret = hitToCaret(firstEndpoint);
        int secondCaret = hitToCaret(secondEndpoint);

        result.append(caretBoundingShape(firstCaret, secondCaret, bounds),
                      false);

        if (firstCaret == 0 || secondCaret == 0) {
            GeneralPath ls = leftShape(bounds);
            if (!ls.getBounds().isEmpty())
                result.append(ls, false);
        }

        if (firstCaret == characterCount || secondCaret == characterCount) {
            GeneralPath rs = rightShape(bounds);
            if (!rs.getBounds().isEmpty()) {
                result.append(rs, false);
            }
        }

        LayoutPathImpl lp = textLine.getLayoutPath();
        if (lp != null) {
            result = (GeneralPath)lp.mapShape(result); // dlf cast safe?
        }

        return  result;
    }

    /**
     * Returns a <code>Shape</code> enclosing the visual selection in the
     * specified range, extended to the bounds.  This method is a
     * convenience overload of <code>getVisualHighlightShape</code> that
     * uses the natural bounds of this <code>TextLayout</code>.
     * @param firstEndpoint one end of the visual selection
     * @param secondEndpoint the other end of the visual selection
     * @return a <code>Shape</code> enclosing the selection.  This is
     *     in standard coordinates.
     */
    public Shape getVisualHighlightShape(TextHitInfo firstEndpoint,
                                             TextHitInfo secondEndpoint) {
        return getVisualHighlightShape(firstEndpoint, secondEndpoint, getNaturalBounds());
    }

    /**
     * Returns a <code>Shape</code> enclosing the logical selection in the
     * specified range, extended to the specified <code>bounds</code>.
     * <p>
     * If the selection range includes the first logical character, the
     * selection is extended to the portion of <code>bounds</code> before
     * the start of this <code>TextLayout</code>.  If the range includes
     * the last logical character, the selection is extended to the portion
     * of <code>bounds</code> after the end of this <code>TextLayout</code>.
     * The height (width on vertical lines) of the selection is always
     * extended to <code>bounds</code>.
     * <p>
     * The selection can be discontiguous on lines with mixed-direction text.
     * Only those characters in the logical range between start and limit
     * appear selected.  For example, consider the text 'ABCdef' where capital
     * letters indicate right-to-left text, rendered on a right-to-left line,
     * with a logical selection from 0 to 4 ('ABCd').  The text appears as
     * follows, with bold standing in for the selection, and underlining for
     * the extension:
     * <br><pre>
     *    <u><b>d</b></u>ef<u><b>CBA  </b></u>
     * </pre>
     * The selection is discontiguous because the selected characters are
     * visually discontiguous. Also note that since the range includes the
     * first logical character (A), the selection is extended to the portion
     * of the <code>bounds</code> before the start of the layout, which in
     * this case (a right-to-left line) is the right portion of the
     * <code>bounds</code>.
     * @param firstEndpoint an endpoint in the range of characters to select
     * @param secondEndpoint the other endpoint of the range of characters
     * to select. Can be less than <code>firstEndpoint</code>.  The range
     * includes the character at min(firstEndpoint, secondEndpoint), but
     * excludes max(firstEndpoint, secondEndpoint).
     * @param bounds the bounding rectangle to which to extend the selection.
     *     This is in baseline-relative coordinates.
     * @return an area enclosing the selection.  This is in standard
     *     coordinates.
     * @see #getVisualHighlightShape(TextHitInfo, TextHitInfo, Rectangle2D)
     */
    public Shape getLogicalHighlightShape(int firstEndpoint,
                                         int secondEndpoint,
                                         Rectangle2D bounds) {
        if (bounds == null) {
            throw new IllegalArgumentException("Null Rectangle2D passed to TextLayout.getLogicalHighlightShape()");
        }

        ensureCache();

        if (firstEndpoint > secondEndpoint) {
            int t = firstEndpoint;
            firstEndpoint = secondEndpoint;
            secondEndpoint = t;
        }

        if(firstEndpoint < 0 || secondEndpoint > characterCount) {
            throw new IllegalArgumentException("Range is invalid in TextLayout.getLogicalHighlightShape()");
        }

        GeneralPath result = new GeneralPath(GeneralPath.WIND_EVEN_ODD);

        int[] carets = new int[10]; // would this ever not handle all cases?
        int count = 0;

        if (firstEndpoint < secondEndpoint) {
            int logIndex = firstEndpoint;
            do {
                carets[count++] = hitToCaret(TextHitInfo.leading(logIndex));
                boolean ltr = textLine.isCharLTR(logIndex);

                do {
                    logIndex++;
                } while (logIndex < secondEndpoint && textLine.isCharLTR(logIndex) == ltr);

                int hitCh = logIndex;
                carets[count++] = hitToCaret(TextHitInfo.trailing(hitCh - 1));

                if (count == carets.length) {
                    int[] temp = new int[carets.length + 10];
                    System.arraycopy(carets, 0, temp, 0, count);
                    carets = temp;
                }
            } while (logIndex < secondEndpoint);
        }
        else {
            count = 2;
            carets[0] = carets[1] = hitToCaret(TextHitInfo.leading(firstEndpoint));
        }

        // now create paths for pairs of carets

        for (int i = 0; i < count; i += 2) {
            result.append(caretBoundingShape(carets[i], carets[i+1], bounds),
                          false);
        }

        if (firstEndpoint != secondEndpoint) {
            if ((textLine.isDirectionLTR() && firstEndpoint == 0) || (!textLine.isDirectionLTR() &&
                                                                      secondEndpoint == characterCount)) {
                GeneralPath ls = leftShape(bounds);
                if (!ls.getBounds().isEmpty()) {
                    result.append(ls, false);
                }
            }

            if ((textLine.isDirectionLTR() && secondEndpoint == characterCount) ||
                (!textLine.isDirectionLTR() && firstEndpoint == 0)) {

                GeneralPath rs = rightShape(bounds);
                if (!rs.getBounds().isEmpty()) {
                    result.append(rs, false);
                }
            }
        }

        LayoutPathImpl lp = textLine.getLayoutPath();
        if (lp != null) {
            result = (GeneralPath)lp.mapShape(result); // dlf cast safe?
        }
        return result;
    }

    /**
     * Returns a <code>Shape</code> enclosing the logical selection in the
     * specified range, extended to the natural bounds of this
     * <code>TextLayout</code>.  This method is a convenience overload of
     * <code>getLogicalHighlightShape</code> that uses the natural bounds of
     * this <code>TextLayout</code>.
     * @param firstEndpoint an endpoint in the range of characters to select
     * @param secondEndpoint the other endpoint of the range of characters
     * to select. Can be less than <code>firstEndpoint</code>.  The range
     * includes the character at min(firstEndpoint, secondEndpoint), but
     * excludes max(firstEndpoint, secondEndpoint).
     * @return a <code>Shape</code> enclosing the selection.  This is in
     *     standard coordinates.
     */
    public Shape getLogicalHighlightShape(int firstEndpoint, int secondEndpoint) {

        return getLogicalHighlightShape(firstEndpoint, secondEndpoint, getNaturalBounds());
    }

    /**
     * Returns the black box bounds of the characters in the specified range.
     * The black box bounds is an area consisting of the union of the bounding
     * boxes of all the glyphs corresponding to the characters between start
     * and limit.  This area can be disjoint.
     * @param firstEndpoint one end of the character range
     * @param secondEndpoint the other end of the character range.  Can be
     * less than <code>firstEndpoint</code>.
     * @return a <code>Shape</code> enclosing the black box bounds.  This is
     *     in standard coordinates.
     */
    public Shape getBlackBoxBounds(int firstEndpoint, int secondEndpoint) {
        ensureCache();

        if (firstEndpoint > secondEndpoint) {
            int t = firstEndpoint;
            firstEndpoint = secondEndpoint;
            secondEndpoint = t;
        }

        if (firstEndpoint < 0 || secondEndpoint > characterCount) {
            throw new IllegalArgumentException("Invalid range passed to TextLayout.getBlackBoxBounds()");
        }

        /*
         * return an area that consists of the bounding boxes of all the
         * characters from firstEndpoint to limit
         */

        GeneralPath result = new GeneralPath(GeneralPath.WIND_NON_ZERO);

        if (firstEndpoint < characterCount) {
            for (int logIndex = firstEndpoint;
                        logIndex < secondEndpoint;
                        logIndex++) {

                Rectangle2D r = textLine.getCharBounds(logIndex);
                if (!r.isEmpty()) {
                    result.append(r, false);
                }
            }
        }

        if (dx != 0 || dy != 0) {
            AffineTransform tx = AffineTransform.getTranslateInstance(dx, dy);
            result = (GeneralPath)tx.createTransformedShape(result);
        }
        LayoutPathImpl lp = textLine.getLayoutPath();
        if (lp != null) {
            result = (GeneralPath)lp.mapShape(result);
        }

        //return new Highlight(result, false);
        return result;
    }

    /**
     * Returns the distance from the point (x,&nbsp;y) to the caret along
     * the line direction defined in <code>caretInfo</code>.  Distance is
     * negative if the point is to the left of the caret on a horizontal
     * line, or above the caret on a vertical line.
     * Utility for use by hitTestChar.
     */
    private float caretToPointDistance(float[] caretInfo, float x, float y) {
        // distanceOffBaseline is negative if you're 'above' baseline

        float lineDistance = isVerticalLine? y : x;
        float distanceOffBaseline = isVerticalLine? -x : y;

        return lineDistance - caretInfo[0] +
            (distanceOffBaseline*caretInfo[1]);
    }

    /**
     * Returns a <code>TextHitInfo</code> corresponding to the
     * specified point.
     * Coordinates outside the bounds of the <code>TextLayout</code>
     * map to hits on the leading edge of the first logical character,
     * or the trailing edge of the last logical character, as appropriate,
     * regardless of the position of that character in the line.  Only the
     * direction along the baseline is used to make this evaluation.
     * @param x the x offset from the origin of this
     *     <code>TextLayout</code>.  This is in standard coordinates.
     * @param y the y offset from the origin of this
     *     <code>TextLayout</code>.  This is in standard coordinates.
     * @param bounds the bounds of the <code>TextLayout</code>.  This
     *     is in baseline-relative coordinates.
     * @return a hit describing the character and edge (leading or trailing)
     *     under the specified point.
     */
    public TextHitInfo hitTestChar(float x, float y, Rectangle2D bounds) {
        // check boundary conditions

        LayoutPathImpl lp = textLine.getLayoutPath();
        boolean prev = false;
        if (lp != null) {
            Point2D.Float pt = new Point2D.Float(x, y);
            prev = lp.pointToPath(pt, pt);
            x = pt.x;
            y = pt.y;
        }

        if (isVertical()) {
            if (y < bounds.getMinY()) {
                return TextHitInfo.leading(0);
            } else if (y >= bounds.getMaxY()) {
                return TextHitInfo.trailing(characterCount-1);
            }
        } else {
            if (x < bounds.getMinX()) {
                return isLeftToRight() ? TextHitInfo.leading(0) : TextHitInfo.trailing(characterCount-1);
            } else if (x >= bounds.getMaxX()) {
                return isLeftToRight() ? TextHitInfo.trailing(characterCount-1) : TextHitInfo.leading(0);
            }
        }

        // revised hit test
        // the original seems too complex and fails miserably with italic offsets
        // the natural tendency is to move towards the character you want to hit
        // so we'll just measure distance to the center of each character's visual
        // bounds, pick the closest one, then see which side of the character's
        // center line (italic) the point is on.
        // this tends to make it easier to hit narrow characters, which can be a
        // bit odd if you're visually over an adjacent wide character. this makes
        // a difference with bidi, so perhaps i need to revisit this yet again.

        double distance = Double.MAX_VALUE;
        int index = 0;
        int trail = -1;
        CoreMetrics lcm = null;
        float icx = 0, icy = 0, ia = 0, cy = 0, dya = 0, ydsq = 0;

        for (int i = 0; i < characterCount; ++i) {
            if (!textLine.caretAtOffsetIsValid(i)) {
                continue;
            }
            if (trail == -1) {
                trail = i;
            }
            CoreMetrics cm = textLine.getCoreMetricsAt(i);
            if (cm != lcm) {
                lcm = cm;
                // just work around baseline mess for now
                if (cm.baselineIndex == GraphicAttribute.TOP_ALIGNMENT) {
                    cy = -(textLine.getMetrics().ascent - cm.ascent) + cm.ssOffset;
                } else if (cm.baselineIndex == GraphicAttribute.BOTTOM_ALIGNMENT) {
                    cy = textLine.getMetrics().descent - cm.descent + cm.ssOffset;
                } else {
                    cy = cm.effectiveBaselineOffset(baselineOffsets) + cm.ssOffset;
                }
                float dy = (cm.descent - cm.ascent) / 2 - cy;
                dya = dy * cm.italicAngle;
                cy += dy;
                ydsq = (cy - y)*(cy - y);
            }
            float cx = textLine.getCharXPosition(i);
            float ca = textLine.getCharAdvance(i);
            float dx = ca / 2;
            cx += dx - dya;

            // proximity in x (along baseline) is two times as important as proximity in y
            double nd = Math.sqrt(4*(cx - x)*(cx - x) + ydsq);
            if (nd < distance) {
                distance = nd;
                index = i;
                trail = -1;
                icx = cx; icy = cy; ia = cm.italicAngle;
            }
        }
        boolean left = x < icx - (y - icy) * ia;
        boolean leading = textLine.isCharLTR(index) == left;
        if (trail == -1) {
            trail = characterCount;
        }
        TextHitInfo result = leading ? TextHitInfo.leading(index) :
            TextHitInfo.trailing(trail-1);
        return result;
    }

    /**
     * Returns a <code>TextHitInfo</code> corresponding to the
     * specified point.  This method is a convenience overload of
     * <code>hitTestChar</code> that uses the natural bounds of this
     * <code>TextLayout</code>.
     * @param x the x offset from the origin of this
     *     <code>TextLayout</code>.  This is in standard coordinates.
     * @param y the y offset from the origin of this
     *     <code>TextLayout</code>.  This is in standard coordinates.
     * @return a hit describing the character and edge (leading or trailing)
     * under the specified point.
     */
    public TextHitInfo hitTestChar(float x, float y) {

        return hitTestChar(x, y, getNaturalBounds());
    }

    /**
     * Returns the hash code of this <code>TextLayout</code>.
     * @return the hash code of this <code>TextLayout</code>.
     */
    public int hashCode() {
        if (hashCodeCache == 0) {
            ensureCache();
            hashCodeCache = textLine.hashCode();
        }
        return hashCodeCache;
    }

    /**
     * Returns <code>true</code> if the specified <code>Object</code> is a
     * <code>TextLayout</code> object and if the specified <code>Object</code>
     * equals this <code>TextLayout</code>.
     * @param obj an <code>Object</code> to test for equality
     * @return <code>true</code> if the specified <code>Object</code>
     *      equals this <code>TextLayout</code>; <code>false</code>
     *      otherwise.
     */
    public boolean equals(Object obj) {
        return (obj instanceof TextLayout) && equals((TextLayout)obj);
    }

    /**
     * Returns <code>true</code> if the two layouts are equal.
     * Two layouts are equal if they contain equal glyphvectors in the same order.
     * @param rhs the <code>TextLayout</code> to compare to this
     *       <code>TextLayout</code>
     * @return <code>true</code> if the specified <code>TextLayout</code>
     *      equals this <code>TextLayout</code>.
     *
     */
    public boolean equals(TextLayout rhs) {

        if (rhs == null) {
            return false;
        }
        if (rhs == this) {
            return true;
        }

        ensureCache();
        return textLine.equals(rhs.textLine);
    }

    /**
     * Returns debugging information for this <code>TextLayout</code>.
     * @return the <code>textLine</code> of this <code>TextLayout</code>
     *        as a <code>String</code>.
     */
    public String toString() {
        ensureCache();
        return textLine.toString();
     }

    /**
     * Renders this <code>TextLayout</code> at the specified location in
     * the specified {@link java.awt.Graphics2D Graphics2D} context.
     * The origin of the layout is placed at x,&nbsp;y.  Rendering may touch
     * any point within <code>getBounds()</code> of this position.  This
     * leaves the <code>g2</code> unchanged.  Text is rendered along the
     * baseline path.
     * @param g2 the <code>Graphics2D</code> context into which to render
     *         the layout
     * @param x the X coordinate of the origin of this <code>TextLayout</code>
     * @param y the Y coordinate of the origin of this <code>TextLayout</code>
     * @see #getBounds()
     */
    public void draw(Graphics2D g2, float x, float y) {

        if (g2 == null) {
            throw new IllegalArgumentException("Null Graphics2D passed to TextLayout.draw()");
        }

        textLine.draw(g2, x - dx, y - dy);
    }

    /**
     * Package-only method for testing ONLY.  Please don't abuse.
     */
    TextLine getTextLineForTesting() {

        return textLine;
    }

    /**
     *
     * Return the index of the first character with a different baseline from the
     * character at start, or limit if all characters between start and limit have
     * the same baseline.
     */
    private static int sameBaselineUpTo(Font font, char[] text,
                                        int start, int limit) {
        // current implementation doesn't support multiple baselines
        return limit;
        /*
        byte bl = font.getBaselineFor(text[start++]);
        while (start < limit && font.getBaselineFor(text[start]) == bl) {
            ++start;
        }
        return start;
        */
    }

    static byte getBaselineFromGraphic(GraphicAttribute graphic) {

        byte alignment = (byte) graphic.getAlignment();

        if (alignment == GraphicAttribute.BOTTOM_ALIGNMENT ||
                alignment == GraphicAttribute.TOP_ALIGNMENT) {

            return (byte)GraphicAttribute.ROMAN_BASELINE;
        }
        else {
            return alignment;
        }
    }

    /**
     * Returns a <code>Shape</code> representing the outline of this
     * <code>TextLayout</code>.
     * @param tx an optional {@link AffineTransform} to apply to the
     *     outline of this <code>TextLayout</code>.
     * @return a <code>Shape</code> that is the outline of this
     *     <code>TextLayout</code>.  This is in standard coordinates.
     */
    public Shape getOutline(AffineTransform tx) {
        ensureCache();
        Shape result = textLine.getOutline(tx);
        LayoutPathImpl lp = textLine.getLayoutPath();
        if (lp != null) {
            result = lp.mapShape(result);
        }
        return result;
    }

    /**
     * Return the LayoutPath, or null if the layout path is the
     * default path (x maps to advance, y maps to offset).
     * @return the layout path
     * @since 1.6
     */
    public LayoutPath getLayoutPath() {
        return textLine.getLayoutPath();
    }

   /**
     * Convert a hit to a point in standard coordinates.  The point is
     * on the baseline of the character at the leading or trailing
     * edge of the character, as appropriate.  If the path is
     * broken at the side of the character represented by the hit, the
     * point will be adjacent to the character.
     * @param hit the hit to check.  This must be a valid hit on
     * the TextLayout.
     * @param point the returned point. The point is in standard
     *     coordinates.
     * @throws IllegalArgumentException if the hit is not valid for the
     * TextLayout.
     * @throws NullPointerException if hit or point is null.
     * @since 1.6
     */
    public void hitToPoint(TextHitInfo hit, Point2D point) {
        if (hit == null || point == null) {
            throw new NullPointerException((hit == null ? "hit" : "point") +
                                           " can't be null");
        }
        ensureCache();
        checkTextHit(hit);

        float adv = 0;
        float off = 0;

        int ix = hit.getCharIndex();
        boolean leading = hit.isLeadingEdge();
        boolean ltr;
        if (ix == -1 || ix == textLine.characterCount()) {
            ltr = textLine.isDirectionLTR();
            adv = (ltr == (ix == -1)) ? 0 : lineMetrics.advance;
        } else {
            ltr = textLine.isCharLTR(ix);
            adv = textLine.getCharLinePosition(ix, leading);
            off = textLine.getCharYPosition(ix);
        }
        point.setLocation(adv, off);
        LayoutPath lp = textLine.getLayoutPath();
        if (lp != null) {
            lp.pathToPoint(point, ltr != leading, point);
        }
    }
}
