001/* LineBreakMeasurer.java
002   Copyright (C) 2006 Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package java.awt.font;
040
041import java.text.AttributedCharacterIterator;
042import java.text.BreakIterator;
043
044public final class LineBreakMeasurer
045{
046  private AttributedCharacterIterator text;
047  private int position;
048  private TextMeasurer tm; 
049  private int numChars;
050
051  public LineBreakMeasurer(AttributedCharacterIterator text, 
052                           BreakIterator breakIter, FontRenderContext frc)
053  {
054    this( text, frc );
055  }
056
057  public LineBreakMeasurer(AttributedCharacterIterator text, 
058                           FontRenderContext frc)
059  {
060    this.text = text;
061    position = 0;
062    numChars = text.getEndIndex();
063    tm = new TextMeasurer( text, frc );
064  }
065
066  public void deleteChar(AttributedCharacterIterator newParagraph, 
067                         int deletePos)
068  {
069    tm.deleteChar( newParagraph, deletePos );
070    position = 0;
071  }
072
073  public void insertChar(AttributedCharacterIterator newParagraph, 
074                         int insertPos)
075  {
076    tm.insertChar( newParagraph, insertPos );
077    position = 0;
078  }
079
080  public TextLayout nextLayout(float wrappingWidth)
081  {
082    return nextLayout( wrappingWidth, numChars, false );
083  }
084
085  public TextLayout nextLayout(float wrappingWidth, int offsetLimit, 
086                               boolean requireNextWord)
087  {
088    int next = nextOffset( wrappingWidth, offsetLimit, requireNextWord );
089    TextLayout tl = tm.getLayout( position, next );
090    position = next;
091    return tl;
092  }
093
094  public int nextOffset(float wrappingWidth)
095  {
096    return nextOffset( wrappingWidth, numChars, false );
097  }
098
099  public int nextOffset(float wrappingWidth, int offsetLimit, 
100                        boolean requireNextWord)
101  {
102    int guessOffset = tm.getLineBreakIndex(position, wrappingWidth);
103    if( offsetLimit > numChars )
104      offsetLimit = numChars;
105
106    if( guessOffset > offsetLimit )
107      {
108        text.setIndex( offsetLimit );
109        return offsetLimit;
110      }
111
112    text.setIndex( guessOffset );
113
114    // If we're on a breaking character, return directly
115    if( Character.isWhitespace( text.current() ) )
116      return guessOffset;
117
118    // Otherwise jump forward or backward to the last such char.
119    if( !requireNextWord )
120      while( !Character.isWhitespace( text.previous() ) && 
121             guessOffset > position )
122        guessOffset--; 
123    else
124      while( !Character.isWhitespace( text.next() ) && 
125             guessOffset < offsetLimit )
126        guessOffset++;
127    
128    if( guessOffset > offsetLimit )
129      {
130        text.setIndex( offsetLimit );
131        return offsetLimit;
132      }
133
134    text.setIndex( guessOffset );
135
136    return guessOffset;
137  }
138
139  public void setPosition(int newPosition)
140  {
141    position = newPosition;
142  }
143
144  public int getPosition()
145  {
146    return position;
147  }
148}
149