/* TextMeasurer.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 java.text.AttributedCharacterIterator;
import java.awt.Shape;

/**
 * TextMeasurer is a small utility class for measuring the length of laid-out
 * text objects. 
 *
 * @author Sven de Marothy
 * @since 1.3
 */
public final class TextMeasurer implements Cloneable
{
  private AttributedCharacterIterator text;
  private FontRenderContext frc;
  private TextLayout totalLayout;
  private int numChars;

  /**
   * Creates a TextMeasurer from a given text in the form of an
   * <code>AttributedCharacterIterator</code> and a 
   * <code>FontRenderContext</code>.
   */  
  public TextMeasurer (AttributedCharacterIterator text, FontRenderContext frc)
  {
    this.text = text;
    this.frc = frc;
    totalLayout = new TextLayout( text, frc );
    numChars = totalLayout.getCharacterCount();
  }

  /**
   * Clones the TextMeasurer object
   */
  protected Object clone ()
  {
    return new TextMeasurer( text, frc );
  }

  /**
   * Update the text if a character is deleted at the position deletePos
   * @param newParagraph - the updated paragraph.
   * @param deletePos - the deletion position
   */
  public void deleteChar (AttributedCharacterIterator newParagraph,
                          int deletePos)
  {
    totalLayout = new TextLayout(newParagraph, frc);
    if( deletePos < 0 || deletePos > totalLayout.getCharacterCount() )
      throw new NullPointerException("Invalid deletePos:"+deletePos);
    numChars = totalLayout.getCharacterCount();
    text = newParagraph;
  }

  /**
   * Update the text if a character is inserted at the position insertPos
   * @param newParagraph - the updated paragraph.
   * @param insertPos - the insertion position
   */
  public void insertChar (AttributedCharacterIterator newParagraph,
                          int insertPos)
  {
    totalLayout = new TextLayout(newParagraph, frc);
    if( insertPos < 0 || insertPos > totalLayout.getCharacterCount() )
      throw new NullPointerException("Invalid insertPos:"+insertPos);
    numChars = totalLayout.getCharacterCount();
    text = newParagraph;
  }

  /***
   * Returns the total advance between two positions in the paragraph.
   * Characters from start to limit-1 (inclusive) are included in this count.
   *
   * @param start - the starting character index.
   * @param limit - the limiting index.
   */
  public float getAdvanceBetween (int start, int limit)
  {
    Shape s = totalLayout.getLogicalHighlightShape( start, limit );
    return (float)s.getBounds2D().getWidth();
  }

  /**
   * Returns a <code>TextLayout</code> object corresponding to the characters
   * from text to limit.
   * @param start - the starting character index.
   * @param limit - the limiting index.
   */
  public TextLayout getLayout (int start, int limit)
  {
    if( start >= limit )
      throw new IllegalArgumentException("Start position must be < limit.");
    return new TextLayout( totalLayout, start, limit );
  }

  /**
   * Returns the line-break index from a given starting index and a maximum
   * advance. The index returned is the first character outside the given
   * advance (or the limit of the string, if all remaining characters fit.)
   *
   * @param start - the starting index.
   * @param maxAdvance - the maximum advance allowed.
   * @return the index of the first character beyond maxAdvance, or the 
   * index of the last character + 1.
   */
  public int getLineBreakIndex (int start, float maxAdvance)
  {   
    if( start < 0 )
      throw new IllegalArgumentException("Start parameter must be > 0.");

    double remainingLength = getAdvanceBetween( start, numChars );
    
    int guessOffset = (int)( ( (double)maxAdvance / (double)remainingLength)
			     * ( (double)numChars - (double)start ) );
    guessOffset += start;
    if( guessOffset > numChars )
      guessOffset = numChars;
    
    double guessLength = getAdvanceBetween( start, guessOffset );
    boolean makeSmaller = ( guessLength > maxAdvance );
    int inc = makeSmaller ? -1 : 1;
    boolean keepGoing = true;

    do
      {
	guessOffset = guessOffset + inc;
	if( guessOffset <= start || guessOffset > numChars )
	  {
	    keepGoing = false;
	  }
	else
	  {
	    guessLength = getAdvanceBetween( start, guessOffset );
	    if( makeSmaller && ( guessLength <= maxAdvance) )	  
	      keepGoing = false;
	    if( !makeSmaller && ( guessLength >= maxAdvance) )
	      keepGoing = false;
	  }
      }
    while( keepGoing );

    // Return first index that doesn't fit.
    if( !makeSmaller )
      guessOffset--;

    if( guessOffset > numChars )
      return numChars;

    return guessOffset;
  }
}
