/* TextLayout.java --
   Copyright (C) 2006  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.awt.font;

import gnu.java.lang.CPStringBuilder;

import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.text.CharacterIterator;
import java.text.AttributedCharacterIterator;
import java.text.Bidi;
import java.util.ArrayList;
import java.util.Map;

/**
 * @author Sven de Marothy
 */
public final class TextLayout implements Cloneable
{
  /**
   * Holds the layout data that belongs to one run of characters.
   */
  private class Run
  {
    /**
     * The actual glyph vector.
     */
    GlyphVector glyphVector;

    /**
     * The font for this text run.
     */
    Font font;

    /**
     * The start of the run.
     */
    int runStart;

    /**
     * The end of the run.
     */
    int runEnd;

    /**
     * The layout location of the beginning of the run.
     */
    float location;

    /**
     * Initializes the Run instance.
     *
     * @param gv the glyph vector
     * @param start the start index of the run
     * @param end the end index of the run
     */
    Run(GlyphVector gv, Font f, int start, int end)
    {
      glyphVector = gv;
      font = f;
      runStart = start;
      runEnd = end;
    }

    /**
     * Returns <code>true</code> when this run is left to right,
     * <code>false</code> otherwise.
     *
     * @return <code>true</code> when this run is left to right,
     *         <code>false</code> otherwise
     */
    boolean isLeftToRight()
    {
      return (glyphVector.getLayoutFlags() & GlyphVector.FLAG_RUN_RTL) == 0;
    }
  }

  /**
   * The laid out character runs.
   */
  private Run[] runs;

  private FontRenderContext frc;
  private char[] string;
  private int offset;
  private int length;
  private Rectangle2D boundsCache;
  private LineMetrics lm;

  /**
   * The total advance of this text layout. This is cache for maximum
   * performance.
   */
  private float totalAdvance = -1F;
  
  /**
   * The cached natural bounds.
   */
  private Rectangle2D naturalBounds;

  /**
   * Character indices.
   * Fixt index is the glyphvector, second index is the (first) glyph.
   */
  private int[][] charIndices;

  /**
   * Base directionality, determined from the first char.
   */
  private boolean leftToRight;

  /**
   * Whether this layout contains whitespace or not.
   */
  private boolean hasWhitespace = false;

  /**
   * The {@link Bidi} object that is used for reordering and by
   * {@link #getCharacterLevel(int)}.
   */
  private Bidi bidi;

  /**
   * Mpas the logical position of each individual character in the original
   * string to its visual position.
   */
  private int[] logicalToVisual;

  /**
   * Maps visual positions of a character to its logical position
   * in the original string.
   */
  private int[] visualToLogical;

  /**
   * The cached hashCode.
   */
  private int hash;

  /**
   * The default caret policy.
   */
  public static final TextLayout.CaretPolicy DEFAULT_CARET_POLICY =
    new CaretPolicy();

  /**
   * Constructs a TextLayout.
   */
  public TextLayout (String str, Font font, FontRenderContext frc) 
  {
    this.frc = frc;
    string = str.toCharArray();
    offset = 0;
    length = this.string.length;
    lm = font.getLineMetrics(this.string, offset, length, frc);

    // Get base direction and whitespace info
    getStringProperties();

    if (Bidi.requiresBidi(string, offset, offset + length))
      {
	bidi = new Bidi(str, leftToRight ? Bidi.DIRECTION_LEFT_TO_RIGHT
                                         : Bidi.DIRECTION_RIGHT_TO_LEFT );
	int rc = bidi.getRunCount();
	byte[] table = new byte[ rc ];
	for(int i = 0; i < table.length; i++)
	  table[i] = (byte)bidi.getRunLevel(i);

        runs = new Run[rc];
	for(int i = 0; i < rc; i++)
	  {
	    int start = bidi.getRunStart(i);
	    int end = bidi.getRunLimit(i);
	    if(start != end) // no empty runs.
	      {
	        GlyphVector gv = font.layoutGlyphVector(frc,
                                                        string, start, end,
                           ((table[i] & 1) == 0) ? Font.LAYOUT_LEFT_TO_RIGHT
                                                 : Font.LAYOUT_RIGHT_TO_LEFT );
                runs[i] = new Run(gv, font, start, end);
              }
	  }
	Bidi.reorderVisually( table, 0, runs, 0, runs.length );
        // Clean up null runs.
        ArrayList cleaned = new ArrayList(rc);
        for (int i = 0; i < rc; i++)
          {
            if (runs[i] != null)
              cleaned.add(runs[i]);
          }
        runs = new Run[cleaned.size()];
        runs = (Run[]) cleaned.toArray(runs);
      }
    else
      {
        GlyphVector gv = font.layoutGlyphVector( frc, string, offset, length,
                                     leftToRight ? Font.LAYOUT_LEFT_TO_RIGHT
                                                 : Font.LAYOUT_RIGHT_TO_LEFT );
        Run run = new Run(gv, font, 0, length);
	runs = new Run[]{ run };
      }
    setCharIndices();
    setupMappings();
    layoutRuns();
  }

  public TextLayout (String string,
		     Map<? extends AttributedCharacterIterator.Attribute, ?> attributes,
		     FontRenderContext frc)  
  {
    this( string, new Font( attributes ), frc );
  }

  public TextLayout (AttributedCharacterIterator text, FontRenderContext frc)
  {
    // FIXME: Very rudimentary.
    this(getText(text), getFont(text), frc);
  }

  /**
   * Package-private constructor to make a textlayout from an existing one.
   * This is used by TextMeasurer for returning sub-layouts, and it 
   * saves a lot of time in not having to relayout the text.
   */
  TextLayout(TextLayout t, int startIndex, int endIndex)
  {
    frc = t.frc;
    boundsCache = null;
    lm = t.lm;
    leftToRight = t.leftToRight;

    if( endIndex > t.getCharacterCount() )
      endIndex = t.getCharacterCount();
    string = t.string;
    offset = startIndex + offset;
    length = endIndex - startIndex;

    int startingRun = t.charIndices[startIndex][0];
    int nRuns = 1 + t.charIndices[endIndex - 1][0] - startingRun;

    runs = new Run[nRuns];
    for( int i = 0; i < nRuns; i++ )
      {
        Run run = t.runs[i + startingRun];
	GlyphVector gv = run.glyphVector;
        Font font = run.font;
	// Copy only the relevant parts of the first and last runs.
	int beginGlyphIndex = (i > 0) ? 0 : t.charIndices[startIndex][1];
	int numEntries = ( i < nRuns - 1) ? gv.getNumGlyphs() : 
	  1 + t.charIndices[endIndex - 1][1] - beginGlyphIndex;
	
	int[] codes = gv.getGlyphCodes(beginGlyphIndex, numEntries, null);
        gv = font.createGlyphVector(frc, codes);
        runs[i] = new Run(gv, font, run.runStart - startIndex,
                          run.runEnd - startIndex);
      }
    runs[nRuns - 1].runEnd = endIndex - 1;

    setCharIndices();
    setupMappings();
    determineWhiteSpace();
    layoutRuns();
  }

  private void setCharIndices()
  {
    charIndices = new int[ getCharacterCount() ][2];
    int i = 0;
    int currentChar = 0;
    for(int run = 0; run < runs.length; run++)
      {
	currentChar = -1;
        Run current = runs[run];
        GlyphVector gv = current.glyphVector;
        for( int gi = 0; gi < gv.getNumGlyphs(); gi++)
          {
            if( gv.getGlyphCharIndex( gi ) != currentChar )
              {
                charIndices[ i ][0] = run;
                charIndices[ i ][1] = gi;
                currentChar = gv.getGlyphCharIndex( gi );
                i++;
              }
          }
      }
  }

  /**
   * Initializes the logicalToVisual and visualToLogial maps.
   */
  private void setupMappings()
  {
    int numChars = getCharacterCount();
    logicalToVisual = new int[numChars];
    visualToLogical = new int[numChars];
    int lIndex = 0;
    int vIndex = 0;
    // We scan the runs in visual order and set the mappings accordingly.
    for (int i = 0; i < runs.length; i++)
      {
        Run run = runs[i];
        if (run.isLeftToRight())
          {
            for (lIndex = run.runStart; lIndex < run.runEnd; lIndex++)
              {
                logicalToVisual[lIndex] = vIndex;
                visualToLogical[vIndex] = lIndex;
                vIndex++;
              }
          }
        else
          {
            for (lIndex = run.runEnd - 1; lIndex >= run.runStart; lIndex--)
              {
                logicalToVisual[lIndex] = vIndex;
                visualToLogical[vIndex] = lIndex;
                vIndex++;
              }
          }
      }
  }

  private static String getText(AttributedCharacterIterator iter)
  {
    CPStringBuilder sb = new CPStringBuilder();
    int idx = iter.getIndex();
    for(char c = iter.first(); c != CharacterIterator.DONE; c = iter.next()) 
      sb.append(c);
    iter.setIndex( idx );
    return sb.toString();
  }

  private static Font getFont(AttributedCharacterIterator iter)
  {
    Font f = (Font)iter.getAttribute(TextAttribute.FONT);
    if( f == null )
      {
	int size;
	Float i = (Float)iter.getAttribute(TextAttribute.SIZE);
	if( i != null )
	  size = (int)i.floatValue();
	else
	  size = 14;
	f = new Font("Dialog", Font.PLAIN, size );
      }
    return f;
  }

  /**
   * Scan the character run for the first strongly directional character,
   * which in turn defines the base directionality of the whole layout.
   */
  private void getStringProperties()
  {
    boolean gotDirection = false;
    int i = offset;
    int endOffs = offset + length;
    leftToRight = true;
    while( i < endOffs && !gotDirection )
      switch( Character.getDirectionality(string[i++]) )
	{
	case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
	case Character.DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING:
	case Character.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE:
	  gotDirection = true;
	  break;
	  
	case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
	case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
	case Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING:
	case Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE:
	  leftToRight = false;
	  gotDirection = true;
	  break;
	}
    determineWhiteSpace();
  }

  private void determineWhiteSpace()
  {
    // Determine if there's whitespace in the thing.
    // Ignore trailing chars.
    int i = offset + length - 1; 
    hasWhitespace = false;
    while( i >= offset && Character.isWhitespace( string[i] ) )
      i--;
    // Check the remaining chars
    while( i >= offset )
      if( Character.isWhitespace( string[i--] ) )
	hasWhitespace = true;
  }

  protected Object clone ()
  {
    return new TextLayout( this, 0, length);
  }

  public void draw (Graphics2D g2, float x, float y) 
  {    
    for(int i = 0; i < runs.length; i++)
      {
        Run run = runs[i];
        GlyphVector gv = run.glyphVector;
        g2.drawGlyphVector(gv, x, y);
        Rectangle2D r = gv.getLogicalBounds();
        x += r.getWidth();
      }
  }

  public boolean equals (Object obj)
  {
    if( !( obj instanceof TextLayout) )
      return false;

    return equals( (TextLayout) obj );
  }

  public boolean equals (TextLayout tl)
  {
    if( runs.length != tl.runs.length )
      return false;
    // Compare all glyph vectors.
    for( int i = 0; i < runs.length; i++ )
      if( !runs[i].equals( tl.runs[i] ) )
	return false;
    return true;
  }

  public float getAdvance ()
  {
    if (totalAdvance == -1F)
      {
        totalAdvance = 0f;
        for(int i = 0; i < runs.length; i++)
          {
            Run run = runs[i];
            GlyphVector gv = run.glyphVector;
            totalAdvance += gv.getLogicalBounds().getWidth();
          }
      }
    return totalAdvance;
  }

  public float getAscent ()
  {
    return lm.getAscent();
  }

  public byte getBaseline ()
  {
    return (byte)lm.getBaselineIndex();
  }

  public float[] getBaselineOffsets ()
  {
    return lm.getBaselineOffsets();
  }

  public Shape getBlackBoxBounds (int firstEndpoint, int secondEndpoint)
  {
    if( secondEndpoint - firstEndpoint <= 0 )
      return new Rectangle2D.Float(); // Hmm? 

    if( firstEndpoint < 0 || secondEndpoint > getCharacterCount())
      return new Rectangle2D.Float();

    GeneralPath gp = new GeneralPath();
    
    int ri = charIndices[ firstEndpoint ][0];
    int gi = charIndices[ firstEndpoint ][1];

    double advance = 0;
   
    for( int i = 0; i < ri; i++ )
      {
        Run run = runs[i];
        GlyphVector gv = run.glyphVector;
        advance += gv.getLogicalBounds().getWidth();
      }
    
    for( int i = ri; i <= charIndices[ secondEndpoint - 1 ][0]; i++ )
      {
        Run run = runs[i];
        GlyphVector gv = run.glyphVector;
	int dg;
	if( i == charIndices[ secondEndpoint - 1 ][0] )
	  dg = charIndices[ secondEndpoint - 1][1];
	else
	  dg = gv.getNumGlyphs() - 1;

	for( int j = 0; j <= dg; j++ )
	  {
	    Rectangle2D r2 = (gv.getGlyphVisualBounds( j )).
	      getBounds2D();
	    Point2D p = gv.getGlyphPosition( j );
	    r2.setRect( advance + r2.getX(), r2.getY(), 
			r2.getWidth(), r2.getHeight() );
	    gp.append(r2, false);
	  }

	advance += gv.getLogicalBounds().getWidth();
      }
    return gp;
  }

  public Rectangle2D getBounds()
  {
    if( boundsCache == null )
      boundsCache = getOutline(new AffineTransform()).getBounds();
    return boundsCache;
  }

  public float[] getCaretInfo (TextHitInfo hit)
  {
    return getCaretInfo(hit, getNaturalBounds());
  }

  public float[] getCaretInfo (TextHitInfo hit, Rectangle2D bounds)
  {
    float[] info = new float[2];
    int index = hit.getCharIndex();
    boolean leading = hit.isLeadingEdge();
    // For the boundary cases we return the boundary runs.
    Run run;
    
    if (index >= length)
      {
        info[0] = getAdvance();
        info[1] = 0;
      }
    else
      {
        if (index < 0)
          {
            run = runs[0];
            index = 0;
            leading = true;
          }
        else
          run = findRunAtIndex(index);

        int glyphIndex = index - run.runStart;
        Shape glyphBounds = run.glyphVector.getGlyphLogicalBounds(glyphIndex);
        Rectangle2D glyphRect = glyphBounds.getBounds2D();
        if (isVertical())
          {
            if (leading)
              info[0] = (float) glyphRect.getMinY();
            else
              info[0] = (float) glyphRect.getMaxY();
          }
        else
          {
            if (leading)
              info[0] = (float) glyphRect.getMinX();
            else
              info[0] = (float) glyphRect.getMaxX();
          }
        info[0] += run.location;
        info[1] = run.font.getItalicAngle();
      }
    return info;
  }

  public Shape getCaretShape(TextHitInfo hit)
  {
    return getCaretShape(hit, getBounds());
  }

  public Shape getCaretShape(TextHitInfo hit, Rectangle2D bounds)
  {
    // TODO: Handle vertical shapes somehow.
    float[] info = getCaretInfo(hit);
    float x1 = info[0];
    float y1 = (float) bounds.getMinY();
    float x2 = info[0];
    float y2 = (float) bounds.getMaxY();
    if (info[1] != 0)
      {
        // Shift x1 and x2 according to the slope.
        x1 -= y1 * info[1];
        x2 -= y2 * info[1];
      }
    GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 2);
    path.moveTo(x1, y1);
    path.lineTo(x2, y2);
    return path;
  }

  public Shape[] getCaretShapes(int offset)
  {
    return getCaretShapes(offset, getNaturalBounds());
  }

  public Shape[] getCaretShapes(int offset, Rectangle2D bounds)
  {
    return getCaretShapes(offset, bounds, DEFAULT_CARET_POLICY);
  }

  public Shape[] getCaretShapes(int offset, Rectangle2D bounds,
                                CaretPolicy policy)
  {
    // The RI returns a 2-size array even when there's only one
    // shape in it.
    Shape[] carets = new Shape[2];
    TextHitInfo hit1 = TextHitInfo.afterOffset(offset);
    int caretHit1 = hitToCaret(hit1);
    TextHitInfo hit2 = hit1.getOtherHit();
    int caretHit2 = hitToCaret(hit2);
    if (caretHit1 == caretHit2)
      {
        carets[0] = getCaretShape(hit1);
        carets[1] = null; // The RI returns null in this seldom case.
      }
    else
      {
        Shape caret1 = getCaretShape(hit1);
        Shape caret2 = getCaretShape(hit2);
        TextHitInfo strong = policy.getStrongCaret(hit1, hit2, this);
        if (strong == hit1)
          {
            carets[0] = caret1;
            carets[1] = caret2;
          }
        else
          {
            carets[0] = caret2;
            carets[1] = caret1;
          }
      }
    return carets;
  }

  public int getCharacterCount ()
  {
    return length;
  }

  public byte getCharacterLevel (int index)
  {
    byte level;
    if( bidi == null )
      level = 0;
    else
      level = (byte) bidi.getLevelAt(index);
    return level;
  }

  public float getDescent ()
  {
    return lm.getDescent();
  }

  public TextLayout getJustifiedLayout (float justificationWidth)
  {
    TextLayout newLayout = (TextLayout)clone();

    if( hasWhitespace )
      newLayout.handleJustify( justificationWidth );

    return newLayout;
  }

  public float getLeading ()
  {
    return lm.getLeading();
  }

  public Shape getLogicalHighlightShape (int firstEndpoint, int secondEndpoint)
  {
    return getLogicalHighlightShape( firstEndpoint, secondEndpoint, 
				     getBounds() );
  }

  public Shape getLogicalHighlightShape (int firstEndpoint, int secondEndpoint,
                                         Rectangle2D bounds)
  {
    if( secondEndpoint - firstEndpoint <= 0 )
      return new Rectangle2D.Float(); // Hmm? 

    if( firstEndpoint < 0 || secondEndpoint > getCharacterCount())
      return new Rectangle2D.Float();

    Rectangle2D r = null;
    int ri = charIndices[ firstEndpoint ][0];
    int gi = charIndices[ firstEndpoint ][1];

    double advance = 0;
   
    for( int i = 0; i < ri; i++ )
      advance += runs[i].glyphVector.getLogicalBounds().getWidth();

    for( int i = ri; i <= charIndices[ secondEndpoint - 1 ][0]; i++ )
      {
        Run run = runs[i];
        GlyphVector gv = run.glyphVector;
	int dg; // last index in this run to use.
	if( i == charIndices[ secondEndpoint - 1 ][0] )
	  dg = charIndices[ secondEndpoint - 1][1];
	else
	  dg = gv.getNumGlyphs() - 1;

	for(; gi <= dg; gi++ )
	  {
	    Rectangle2D r2 = (gv.getGlyphLogicalBounds( gi )).
	      getBounds2D();
	    if( r == null )
	      r = r2;
	    else
	      r = r.createUnion(r2);
	  }
	gi = 0; // reset glyph index into run for next run.

	advance += gv.getLogicalBounds().getWidth();
      }

    return r;
  }

  public int[] getLogicalRangesForVisualSelection (TextHitInfo firstEndpoint,
                                                   TextHitInfo secondEndpoint)
  {
    // Check parameters.
    checkHitInfo(firstEndpoint);
    checkHitInfo(secondEndpoint);

    // Convert to visual and order correctly.
    int start = hitToCaret(firstEndpoint);
    int end = hitToCaret(secondEndpoint);
    if (start > end)
      {
        // Swap start and end so that end >= start.
        int temp = start;
        start = end;
        end = temp;
      }

    // Now walk through the visual indices and mark the included pieces.
    boolean[] include = new boolean[length];
    for (int i = start; i < end; i++)
      {
        include[visualToLogical[i]] = true;
      }

    // Count included runs.
    int numRuns = 0;
    boolean in = false;
    for (int i = 0; i < length; i++)
      {
        if (include[i] != in) // At each run in/out point we toggle the in var.
          {
            in = ! in;
            if (in) // At each run start we count up.
              numRuns++;
          }
      }

    // Put together the ranges array.
    int[] ranges = new int[numRuns * 2];
    int index = 0;
    in = false;
    for (int i = 0; i < length; i++)
      {
        if (include[i] != in)
          {
            ranges[index] = i;
            index++;
            in = ! in;
          }
      }
    // If the last run ends at the very end, include that last bit too.
    if (in)
      ranges[index] = length;

    return ranges;
  }

  public TextHitInfo getNextLeftHit(int offset)
  {
    return getNextLeftHit(offset, DEFAULT_CARET_POLICY);
  }

  public TextHitInfo getNextLeftHit(int offset, CaretPolicy policy)
  {
    if (policy == null)
      throw new IllegalArgumentException("Null policy not allowed");
    if (offset < 0 || offset > length)
      throw new IllegalArgumentException("Offset out of bounds");

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

    TextHitInfo strong = policy.getStrongCaret(hit1, hit2, this);
    TextHitInfo next = getNextLeftHit(strong);
    TextHitInfo ret = null;
    if (next != null)
      {
        TextHitInfo next2 = getVisualOtherHit(next);
        ret = policy.getStrongCaret(next2, next, this);
      }
    return ret;
  }

  public TextHitInfo getNextLeftHit (TextHitInfo hit)
  {
    checkHitInfo(hit);
    int index = hitToCaret(hit);
    TextHitInfo next = null;
    if (index != 0)
      {
        index--;
        next = caretToHit(index);
      }
    return next;
  }

  public TextHitInfo getNextRightHit(int offset)
  {
    return getNextRightHit(offset, DEFAULT_CARET_POLICY);
  }

  public TextHitInfo getNextRightHit(int offset, CaretPolicy policy)
  {
    if (policy == null)
      throw new IllegalArgumentException("Null policy not allowed");
    if (offset < 0 || offset > length)
      throw new IllegalArgumentException("Offset out of bounds");

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

    TextHitInfo next = getNextRightHit(policy.getStrongCaret(hit1, hit2, this));
    TextHitInfo ret = null;
    if (next != null)
      {
        TextHitInfo next2 = getVisualOtherHit(next);
        ret = policy.getStrongCaret(next2, next, this);
      }
    return ret;
  }

  public TextHitInfo getNextRightHit(TextHitInfo hit)
  {
    checkHitInfo(hit);
    int index = hitToCaret(hit);
    TextHitInfo next = null;
    if (index < length)
      {
        index++;
        next = caretToHit(index);
      }
    return next;
  }

  public Shape getOutline (AffineTransform tx)
  {
    float x = 0f;
    GeneralPath gp = new GeneralPath();
    for(int i = 0; i < runs.length; i++)
      {
        GlyphVector gv = runs[i].glyphVector;
	gp.append( gv.getOutline( x, 0f ), false );
	Rectangle2D r = gv.getLogicalBounds();
	x += r.getWidth();
      }
    if( tx != null )
      gp.transform( tx );
    return gp;
  }

  public float getVisibleAdvance ()
  {
    float totalAdvance = 0f;

    if( runs.length <= 0 )
      return 0f;

    // No trailing whitespace
    if( !Character.isWhitespace( string[offset + length - 1]) )
      return getAdvance();

    // Get length of all runs up to the last
    for(int i = 0; i < runs.length - 1; i++)
      totalAdvance += runs[i].glyphVector.getLogicalBounds().getWidth();

    int lastRun = runs[runs.length - 1].runStart;
    int j = length - 1;
    while( j >= lastRun && Character.isWhitespace( string[j] ) ) j--;

    if( j < lastRun )
      return totalAdvance; // entire last run is whitespace

    int lastNonWSChar = j - lastRun;
    j = 0;
    while( runs[ runs.length - 1 ].glyphVector.getGlyphCharIndex( j )
	   <= lastNonWSChar )
      {
	totalAdvance += runs[ runs.length - 1 ].glyphVector
                                               .getGlyphLogicalBounds( j )
                                               .getBounds2D().getWidth();
	j ++;
      }
    
    return totalAdvance;
  }

  public Shape getVisualHighlightShape (TextHitInfo firstEndpoint,
                                        TextHitInfo secondEndpoint)
  {
    return getVisualHighlightShape( firstEndpoint, secondEndpoint, 
				    getBounds() );
  }

  public Shape getVisualHighlightShape (TextHitInfo firstEndpoint,
                                        TextHitInfo secondEndpoint,
                                        Rectangle2D bounds)
  {
    GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
    Shape caret1 = getCaretShape(firstEndpoint, bounds);
    path.append(caret1, false);
    Shape caret2 = getCaretShape(secondEndpoint, bounds);
    path.append(caret2, false);
    // Append left (top) bounds to selection if necessary.
    int c1 = hitToCaret(firstEndpoint);
    int c2 = hitToCaret(secondEndpoint);
    if (c1 == 0 || c2 == 0)
      {
        path.append(left(bounds), false);
      }
    // Append right (bottom) bounds if necessary.
    if (c1 == length || c2 == length)
      {
        path.append(right(bounds), false);
      }
    return path.getBounds2D();
  }

  /**
   * Returns the shape that makes up the left (top) edge of this text layout.
   *
   * @param b the bounds
   *
   * @return the shape that makes up the left (top) edge of this text layout
   */
  private Shape left(Rectangle2D b)
  {
    GeneralPath left = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
    left.append(getCaretShape(TextHitInfo.beforeOffset(0)), false);
    if (isVertical())
      {
        float y = (float) b.getMinY();
        left.append(new Line2D.Float((float) b.getMinX(), y,
                                     (float) b.getMaxX(), y), false);
      }
    else
      {
        float x = (float) b.getMinX();
        left.append(new Line2D.Float(x, (float) b.getMinY(),
                                     x, (float) b.getMaxY()), false);
      }
    return left.getBounds2D();
  }

  /**
   * Returns the shape that makes up the right (bottom) edge of this text
   * layout.
   *
   * @param b the bounds
   *
   * @return the shape that makes up the right (bottom) edge of this text
   *         layout
   */
  private Shape right(Rectangle2D b)
  {
    GeneralPath right = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
    right.append(getCaretShape(TextHitInfo.afterOffset(length)), false);
    if (isVertical())
      {
        float y = (float) b.getMaxY();
        right.append(new Line2D.Float((float) b.getMinX(), y,
                                      (float) b.getMaxX(), y), false);
      }
    else
      {
        float x = (float) b.getMaxX();
        right.append(new Line2D.Float(x, (float) b.getMinY(),
                                      x, (float) b.getMaxY()), false);
      }
    return right.getBounds2D();
  }

  public TextHitInfo getVisualOtherHit (TextHitInfo hit)
  {
    checkHitInfo(hit);
    int hitIndex = hit.getCharIndex();

    int index;
    boolean leading;
    if (hitIndex == -1 || hitIndex == length)
      {
        // Boundary case.
        int visual;
        if (isLeftToRight() == (hitIndex == -1))
          visual = 0;
        else
          visual = length - 1;
        index = visualToLogical[visual];
        if (isLeftToRight() == (hitIndex == -1))
          leading = isCharacterLTR(index); // LTR.
        else
          leading = ! isCharacterLTR(index); // RTL.
      }
    else
      {
        // Normal case.
        int visual = logicalToVisual[hitIndex];
        boolean b;
        if (isCharacterLTR(hitIndex) == hit.isLeadingEdge())
          {
            visual--;
            b = false;
          }
        else
          {
            visual++;
            b = true;
          }
        if (visual >= 0 && visual < length)
          {
            index = visualToLogical[visual];
            leading = b == isLeftToRight();
          }
        else
          {
            index = b == isLeftToRight() ? length : -1;
            leading = index == length;
          }
      }
    return leading ? TextHitInfo.leading(index) : TextHitInfo.trailing(index);
  }

  /**
   * This is a protected method of a <code>final</code> class, meaning
   * it exists only to taunt you.
   */
  protected void handleJustify (float justificationWidth)
  {
    // We assume that the text has non-trailing whitespace.
    // First get the change in width to insert into the whitespaces.
    double deltaW = justificationWidth - getVisibleAdvance();
    int nglyphs = 0; // # of whitespace chars

    // determine last non-whitespace char.
    int lastNWS = offset + length - 1;
    while( Character.isWhitespace( string[lastNWS] ) ) lastNWS--;

    // locations of the glyphs.
    int[] wsglyphs = new int[length * 10];
    for(int run = 0; run < runs.length; run++ )
      {
      Run current = runs[run];
      for(int i = 0; i < current.glyphVector.getNumGlyphs(); i++ )
	{
	  int cindex = current.runStart
                       + current.glyphVector.getGlyphCharIndex( i );
	  if( Character.isWhitespace( string[cindex] ) )
	    //	      && cindex < lastNWS )
	    {
	      wsglyphs[ nglyphs * 2 ] = run;
	      wsglyphs[ nglyphs * 2 + 1] = i;
	      nglyphs++;
	    }
	}
      }
    deltaW = deltaW / nglyphs; // Change in width per whitespace glyph
    double w = 0;
    int cws = 0;
    // Shift all characters
    for(int run = 0; run < runs.length; run++ )
      {
        Run current = runs[run];
        for(int i = 0; i < current.glyphVector.getNumGlyphs(); i++ )
          {
            if( wsglyphs[ cws * 2 ] == run && wsglyphs[ cws * 2 + 1 ] == i )
              {
                cws++; // update 'current whitespace'
                w += deltaW; // increment the shift
              }
            Point2D p = current.glyphVector.getGlyphPosition( i );
            p.setLocation( p.getX() + w, p.getY() );
            current.glyphVector.setGlyphPosition( i, p );
          }
      }
  }

  public TextHitInfo hitTestChar (float x, float y)
  {
    return hitTestChar(x, y, getNaturalBounds());
  }

  /**
   * Finds the character hit at the specified point. This 'clips' this
   * text layout against the specified <code>bounds</code> rectangle. That
   * means that in the case where a point is outside these bounds, this method
   * returns the leading edge of the first character or the trailing edge of
   * the last character.
   *
   * @param x the X location to test
   * @param y the Y location to test
   * @param bounds the bounds to test against
   *
   * @return the character hit at the specified point
   */
  public TextHitInfo hitTestChar (float x, float y, Rectangle2D bounds)
  {
    // Check bounds.
    if (isVertical())
      {
        if (y < bounds.getMinY())
          return TextHitInfo.leading(0);
        else if (y > bounds.getMaxY())
          return TextHitInfo.trailing(getCharacterCount() - 1);
      }
    else
      {
        if (x < bounds.getMinX())
          return TextHitInfo.leading(0);
        else if (x > bounds.getMaxX())
          return TextHitInfo.trailing(getCharacterCount() - 1);
      }

    TextHitInfo hitInfo = null;
    if (isVertical())
      {
        // Search for the run at the location.
        // TODO: Perform binary search for maximum efficiency. However, we
        // need the run location laid out statically to do that.
        int numRuns = runs.length;
        Run hitRun = null;
        for (int i = 0; i < numRuns && hitRun == null; i++)
          {
            Run run = runs[i];
            Rectangle2D lBounds = run.glyphVector.getLogicalBounds();
            if (lBounds.getMinY() + run.location <= y
                && lBounds.getMaxY() + run.location >= y)
              hitRun = run;
          }
        // Now we have (hopefully) found a run that hits. Now find the
        // right character.
        if (hitRun != null)
          {
            GlyphVector gv = hitRun.glyphVector;
            for (int i = hitRun.runStart;
                 i < hitRun.runEnd && hitInfo == null; i++)
              {
                int gi = i - hitRun.runStart;
                Rectangle2D lBounds = gv.getGlyphLogicalBounds(gi)
                                      .getBounds2D();
                if (lBounds.getMinY() + hitRun.location <= y
                    && lBounds.getMaxY() + hitRun.location >= y)
                  {
                    // Found hit. Now check if we are leading or trailing.
                    boolean leading = true;
                    if (lBounds.getCenterY() + hitRun.location <= y)
                      leading = false;
                    hitInfo = leading ? TextHitInfo.leading(i)
                                      : TextHitInfo.trailing(i);
                  }
              }
          }
      }
    else
      {
        // Search for the run at the location.
        // TODO: Perform binary search for maximum efficiency. However, we
        // need the run location laid out statically to do that.
        int numRuns = runs.length;
        Run hitRun = null;
        for (int i = 0; i < numRuns && hitRun == null; i++)
          {
            Run run = runs[i];
            Rectangle2D lBounds = run.glyphVector.getLogicalBounds();
            if (lBounds.getMinX() + run.location <= x
                && lBounds.getMaxX() + run.location >= x)
              hitRun = run;
          }
        // Now we have (hopefully) found a run that hits. Now find the
        // right character.
        if (hitRun != null)
          {
            GlyphVector gv = hitRun.glyphVector;
            for (int i = hitRun.runStart;
                 i < hitRun.runEnd && hitInfo == null; i++)
              {
                int gi = i - hitRun.runStart;
                Rectangle2D lBounds = gv.getGlyphLogicalBounds(gi)
                                      .getBounds2D();
                if (lBounds.getMinX() + hitRun.location <= x
                    && lBounds.getMaxX() + hitRun.location >= x)
                  {
                    // Found hit. Now check if we are leading or trailing.
                    boolean leading = true;
                    if (lBounds.getCenterX() + hitRun.location <= x)
                      leading = false;
                    hitInfo = leading ? TextHitInfo.leading(i)
                                      : TextHitInfo.trailing(i);
                  }
              }
          }
      }
    return hitInfo;
  }

  public boolean isLeftToRight ()
  {
    return leftToRight;
  }

  public boolean isVertical ()
  {
    return false; // FIXME: How do you create a vertical layout?
  }

  public int hashCode ()
  {
    // This is implemented in sync to equals().
    if (hash == 0 && runs.length > 0)
      {
        hash = runs.length;
        for (int i = 0; i < runs.length; i++)
          hash ^= runs[i].glyphVector.hashCode();
      }
    return hash;
  }

  public String toString ()
  {
    return "TextLayout [string:"+ new String(string, offset, length)
    +" Rendercontext:"+
      frc+"]";
  }

  /**
   * Returns the natural bounds of that text layout. This is made up
   * of the ascent plus descent and the text advance.
   *
   * @return the natural bounds of that text layout
   */
  private Rectangle2D getNaturalBounds()
  {
    if (naturalBounds == null)
      naturalBounds = new Rectangle2D.Float(0.0F, -getAscent(), getAdvance(),
                                            getAscent() + getDescent());
    return naturalBounds;
  }

  private void checkHitInfo(TextHitInfo hit)
  {
    if (hit == null)
      throw new IllegalArgumentException("Null hit info not allowed");
    int index = hit.getInsertionIndex();
    if (index < 0 || index > length)
      throw new IllegalArgumentException("Hit index out of range");
  }

  private int hitToCaret(TextHitInfo hit)
  {
    int index = hit.getCharIndex();
    int ret;
    if (index < 0)
      ret = isLeftToRight() ? 0 : length;
    else if (index >= length)
      ret = isLeftToRight() ? length : 0;
    else
      {
        ret = logicalToVisual[index];
        if (hit.isLeadingEdge() != isCharacterLTR(index))
          ret++;
      }
    return ret;
  }

  private TextHitInfo caretToHit(int index)
  {
    TextHitInfo hit;
    if (index == 0 || index == length)
      {
        if ((index == length) == isLeftToRight())
          hit = TextHitInfo.leading(length);
        else
          hit = TextHitInfo.trailing(-1);
      }
    else
      {
        int logical = visualToLogical[index];
        boolean leading = isCharacterLTR(logical); // LTR.
        hit = leading ? TextHitInfo.leading(logical)
                      : TextHitInfo.trailing(logical);
      }
    return hit;
  }

  private boolean isCharacterLTR(int index)
  {
    byte level = getCharacterLevel(index);
    return (level & 1) == 0;
  }

  /**
   * Finds the run that holds the specified (logical) character index. This
   * returns <code>null</code> when the index is not inside the range.
   *
   * @param index the index of the character to find
   *
   * @return the run that holds the specified character
   */
  private Run findRunAtIndex(int index)
  {
    Run found = null;
    // TODO: Can we do better than linear searching here?
    for (int i = 0; i < runs.length && found == null; i++)
      {
        Run run = runs[i];
        if (run.runStart <= index && run.runEnd > index)
          found = run;
      }
    return found;
  }

  /**
   * Computes the layout locations for each run.
   */
  private void layoutRuns()
  {
    float loc = 0.0F;
    float lastWidth = 0.0F;
    for (int i = 0; i < runs.length; i++)
      {
        runs[i].location = loc;
        Rectangle2D bounds = runs[i].glyphVector.getLogicalBounds();
        loc += isVertical() ? bounds.getHeight() : bounds.getWidth();
      }
  }

  /**
   * Inner class describing a caret policy
   */
  public static class CaretPolicy
  {
    public CaretPolicy()
    {
    }

    public TextHitInfo getStrongCaret(TextHitInfo hit1,
				      TextHitInfo hit2,
				      TextLayout layout)
    {
      byte l1 = layout.getCharacterLevel(hit1.getCharIndex());
      byte l2 = layout.getCharacterLevel(hit2.getCharIndex());
      TextHitInfo strong;
      if (l1 == l2)
        {
          if (hit2.isLeadingEdge() && ! hit1.isLeadingEdge())
            strong = hit2;
          else
            strong = hit1;
        }
      else
        {
          if (l1 < l2)
            strong = hit1;
          else
            strong = hit2;
        }
      return strong;
    }
  }
}


