Source for java.awt.font.LineBreakMeasurer

   1: /* LineBreakMeasurer.java
   2:    Copyright (C) 2006 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package java.awt.font;
  40: 
  41: import java.text.AttributedCharacterIterator;
  42: import java.text.AttributedString;
  43: import java.text.BreakIterator;
  44: import java.awt.font.TextLayout;
  45: import java.awt.font.FontRenderContext;
  46: import java.awt.Shape;
  47: 
  48: public final class LineBreakMeasurer
  49: {
  50:   private AttributedCharacterIterator text;
  51:   private int position;
  52:   private FontRenderContext frc;
  53:   private TextLayout totalLayout;
  54:   private int numChars;
  55: 
  56:   public LineBreakMeasurer(AttributedCharacterIterator text, 
  57:                BreakIterator breakIter, FontRenderContext frc)
  58:   {
  59:     this.text = text;
  60:     this.frc = frc;
  61:     position = 0;
  62:     totalLayout = new TextLayout(text, frc);
  63:     numChars = totalLayout.getCharacterCount();
  64:   }
  65: 
  66:   public LineBreakMeasurer(AttributedCharacterIterator text, 
  67:                FontRenderContext frc)
  68:   {
  69:     this.text = text;
  70:     this.frc = frc;
  71:     position = 0;
  72:     totalLayout = new TextLayout(text, frc);
  73:     numChars = totalLayout.getCharacterCount();
  74:   }
  75: 
  76:   public void deleteChar(AttributedCharacterIterator newParagraph, 
  77:              int deletePos)
  78:   {
  79:     totalLayout = new TextLayout(newParagraph, frc);
  80:     if( deletePos < 0 || deletePos > totalLayout.getCharacterCount() )
  81:       throw new NullPointerException("Invalid deletePos:"+deletePos);
  82:     numChars = totalLayout.getCharacterCount();
  83:     text = newParagraph;
  84:     position = 0;
  85:   }
  86: 
  87:   public void insertChar(AttributedCharacterIterator newParagraph, 
  88:              int insertPos)
  89:   {
  90:     totalLayout = new TextLayout(newParagraph, frc);
  91:     if( insertPos < 0 || insertPos > totalLayout.getCharacterCount() )
  92:       throw new NullPointerException("Invalid insertPos:"+insertPos);
  93:     numChars = totalLayout.getCharacterCount();
  94:     text = newParagraph;
  95:     position = 0;
  96:   }
  97: 
  98:   public TextLayout nextLayout(float wrappingWidth)
  99:   {
 100:     return nextLayout( wrappingWidth, numChars, false );
 101:   }
 102: 
 103:   public TextLayout nextLayout(float wrappingWidth, int offsetLimit, 
 104:                    boolean requireNextWord)
 105:   {
 106:     int next = nextOffset( wrappingWidth, offsetLimit, requireNextWord );
 107:     AttributedCharacterIterator aci = (new AttributedString( text, 
 108:                                  position, next )
 109:                        ).getIterator();
 110:     position = next;
 111:     return new TextLayout( aci, frc );
 112:   }
 113: 
 114:   public int nextOffset(float wrappingWidth)
 115:   {
 116:     return nextOffset( wrappingWidth, numChars, false );
 117:   }
 118: 
 119:   public int nextOffset(float wrappingWidth, int offsetLimit, 
 120:             boolean requireNextWord)
 121:   {
 122:     Shape s = totalLayout.getBlackBoxBounds( position, offsetLimit );
 123:     double remainingLength = s.getBounds2D().getWidth();
 124: 
 125:     int guessOffset = (int)( ( (double)wrappingWidth / (double)remainingLength)
 126:                  * ( (double)numChars - (double)position ) );
 127:     guessOffset += position;
 128:     if( guessOffset > offsetLimit )
 129:       guessOffset = offsetLimit;
 130: 
 131:     s = totalLayout.getBlackBoxBounds( position, guessOffset );
 132:     double guessLength = s.getBounds2D().getWidth();
 133: 
 134:     boolean makeSmaller = ( guessLength > wrappingWidth );
 135:     int inc = makeSmaller ? -1 : 1;
 136:     boolean keepGoing = true;
 137: 
 138:     do
 139:       {
 140:     guessOffset = guessOffset + inc;
 141:     if( guessOffset <= position || guessOffset > offsetLimit )
 142:       {
 143:         keepGoing = false;
 144:       }
 145:     else
 146:       {
 147:         s = totalLayout.getBlackBoxBounds( position, guessOffset );
 148:         guessLength = s.getBounds2D().getWidth();
 149:         if( makeSmaller && ( guessLength <= wrappingWidth) )      
 150:           keepGoing = false;
 151:         if( !makeSmaller && ( guessLength >= wrappingWidth) )
 152:           keepGoing = false;
 153:       }
 154:       }
 155:     while( keepGoing );
 156: 
 157:     if( !makeSmaller )
 158:       guessOffset--;
 159: 
 160:     if( guessOffset >= offsetLimit )
 161:       return offsetLimit;
 162: 
 163:     text.setIndex( guessOffset );
 164:     if( !requireNextWord )
 165:       {
 166:     char c = text.previous();
 167:     while( !Character.isWhitespace( c ) && c != '-' && 
 168:            guessOffset > position )
 169:       { 
 170:         guessOffset--; 
 171:         c = text.previous();
 172:       }
 173:       }
 174:     else
 175:       {
 176:     char c = text.next();
 177:     while( !Character.isWhitespace( c ) && c != '-' && 
 178:            guessOffset < offsetLimit )
 179:       {
 180:         guessOffset++;
 181:         c = text.next();
 182:       }
 183:       }
 184: 
 185:     return guessOffset;
 186:   }
 187: 
 188:   public void setPosition(int newPosition)
 189:   {
 190:     position = newPosition;
 191:   }
 192: 
 193:   public int getPosition()
 194:   {
 195:     return position;
 196:   }
 197: }