commit-classpath
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[commit-cp] classpath ChangeLog gnu/java/awt/peer/gtk/Freet...


From: Sven de Marothy
Subject: [commit-cp] classpath ChangeLog gnu/java/awt/peer/gtk/Freet...
Date: Sun, 18 Jun 2006 00:54:48 +0000

CVSROOT:        /sources/classpath
Module name:    classpath
Changes by:     Sven de Marothy <smarothy>      06/06/18 00:54:47

Modified files:
        .              : ChangeLog 
        gnu/java/awt/peer/gtk: FreetypeGlyphVector.java 
        java/awt/font  : LineBreakMeasurer.java TextLayout.java 
                         TextMeasurer.java 
        java/text      : AttributedString.java 

Log message:
        2006-06-18  Sven de Marothy  <address@hidden>
        
                * gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
                (FreetypeGlyphVector, clone): Implement cloning.
                (getGlyphLogicalBounds): Bounds should be offset to the glyph 
position.
                * java/awt/font/TextMeasurer.java: Implement.
                * java/awt/font/LineBreakMeasurer.java: 
                Reimplement to use TextMeasurer.
                * java/awt/font/TextLayout.java
                New constructors.
                (getBlackboxBounds, getLogicalHighlightShape): Reimplement.
                (getText, getFont): New private static methods.
                (setCharIndices): New method.
                * java/text/AttributedString.java
                (AttributedString): Fix constructor to stop at end point.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/classpath/ChangeLog?cvsroot=classpath&r1=1.7861&r2=1.7862
http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java?cvsroot=classpath&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/classpath/java/awt/font/LineBreakMeasurer.java?cvsroot=classpath&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/classpath/java/awt/font/TextLayout.java?cvsroot=classpath&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/classpath/java/awt/font/TextMeasurer.java?cvsroot=classpath&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/classpath/java/text/AttributedString.java?cvsroot=classpath&r1=1.15&r2=1.16

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/classpath/classpath/ChangeLog,v
retrieving revision 1.7861
retrieving revision 1.7862
diff -u -b -r1.7861 -r1.7862
--- ChangeLog   17 Jun 2006 23:58:41 -0000      1.7861
+++ ChangeLog   18 Jun 2006 00:54:46 -0000      1.7862
@@ -1,4 +1,20 @@
-2006-0-12  Mario torre  <neugens at limasoftware.net>
+2006-06-18  Sven de Marothy  <address@hidden>
+
+       * gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
+       (FreetypeGlyphVector, clone): Implement cloning.
+       (getGlyphLogicalBounds): Bounds should be offset to the glyph position.
+       * java/awt/font/TextMeasurer.java: Implement.
+       * java/awt/font/LineBreakMeasurer.java: 
+       Reimplement to use TextMeasurer.
+       * java/awt/font/TextLayout.java
+       New constructors.
+       (getBlackboxBounds, getLogicalHighlightShape): Reimplement.
+       (getText, getFont): New private static methods.
+       (setCharIndices): New method.
+       * java/text/AttributedString.java
+       (AttributedString): Fix constructor to stop at end point.
+       
+2006-06-12  Mario torre  <neugens at limasoftware.net>
 
        * gnu/java/util/prefs/GConfBasedPreferences.java: new class.
        * gnu/java/util/prefs/GConfBasedFactory.java: new class.

Index: gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
===================================================================
RCS file: 
/sources/classpath/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- gnu/java/awt/peer/gtk/FreetypeGlyphVector.java      11 Jun 2006 08:29:57 
-0000      1.6
+++ gnu/java/awt/peer/gtk/FreetypeGlyphVector.java      18 Jun 2006 00:54:47 
-0000      1.7
@@ -137,6 +137,35 @@
   }
 
   /**
+   * Cloning constructor
+   */  
+  private FreetypeGlyphVector( FreetypeGlyphVector gv )
+  {
+    font = gv.font;
+    peer = gv.peer;
+    frc = gv.frc;
+    s = gv.s;
+    nGlyphs = gv.nGlyphs;
+    logicalBounds = gv.logicalBounds.getBounds2D();
+
+    if( gv.metricsCache != null )
+      {
+       metricsCache = new GlyphMetrics[ nGlyphs ];
+       System.arraycopy(gv.metricsCache, 0, metricsCache, 0, nGlyphs);
+      }
+
+    glyphCodes = new int[ nGlyphs ];
+    glyphPositions = new float[ nGlyphs ];
+    glyphTransforms = new AffineTransform[ nGlyphs ];
+    for(int i = 0; i < nGlyphs; i++ )
+      {
+       glyphTransforms[ i ] = new AffineTransform( gv.glyphTransforms[ i ] );
+       glyphCodes[i] = gv.glyphCodes[ i ];
+       glyphPositions[i] = gv.glyphPositions[ i ];
+      }
+  }
+
+  /**
    * Create the array of glyph codes.
    */
   private void getGlyphs()
@@ -172,6 +201,12 @@
 
   private native GeneralPath getGlyphOutlineNative(int glyphIndex);
 
+
+  public Object clone()
+  {
+    return new FreetypeGlyphVector( this );
+  }
+
   /**
    * Duh, compares two instances.
    */
@@ -260,8 +295,11 @@
     if( gm == null )
       return null; 
     Rectangle2D r = gm.getBounds2D();
-    return new Rectangle2D.Double( r.getX() - gm.getLSB(), r.getY(),
-                                  gm.getAdvanceX(), r.getHeight() );
+    Point2D p = getGlyphPosition( glyphIndex );
+    return new Rectangle2D.Double( p.getX() + r.getX() - gm.getLSB(), 
+                                  p.getY() + r.getY(),
+                                  gm.getAdvanceX(), 
+                                  r.getHeight() );
   }
 
   /*
@@ -385,8 +423,6 @@
     for( int i = 1; i < nGlyphs; i++ )
       {
        Rectangle2D r2 = (Rectangle2D)getGlyphLogicalBounds( i );
-       Point2D p = getGlyphPosition( i );
-       r2.setRect( p.getX(), p.getY(), r2.getWidth(), r2.getHeight() );
        rect = rect.createUnion( r2 );
       }
 

Index: java/awt/font/LineBreakMeasurer.java
===================================================================
RCS file: /sources/classpath/classpath/java/awt/font/LineBreakMeasurer.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- java/awt/font/LineBreakMeasurer.java        13 Jun 2006 00:14:27 -0000      
1.4
+++ java/awt/font/LineBreakMeasurer.java        18 Jun 2006 00:54:47 -0000      
1.5
@@ -41,57 +41,41 @@
 import java.text.AttributedCharacterIterator;
 import java.text.AttributedString;
 import java.text.BreakIterator;
-import java.awt.font.TextLayout;
-import java.awt.font.FontRenderContext;
 import java.awt.Shape;
 
 public final class LineBreakMeasurer
 {
   private AttributedCharacterIterator text;
   private int position;
-  private FontRenderContext frc;
-  private TextLayout totalLayout;
+  private TextMeasurer tm; 
   private int numChars;
 
   public LineBreakMeasurer(AttributedCharacterIterator text, 
                           BreakIterator breakIter, FontRenderContext frc)
   {
-    this.text = text;
-    this.frc = frc;
-    position = 0;
-    totalLayout = new TextLayout(text, frc);
-    numChars = totalLayout.getCharacterCount();
+    this( text, frc );
   }
 
   public LineBreakMeasurer(AttributedCharacterIterator text, 
                           FontRenderContext frc)
   {
     this.text = text;
-    this.frc = frc;
     position = 0;
-    totalLayout = new TextLayout(text, frc);
-    numChars = totalLayout.getCharacterCount();
+    numChars = text.getEndIndex();
+    tm = new TextMeasurer( text, frc );
   }
 
   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;
+    tm.deleteChar( newParagraph, deletePos );
     position = 0;
   }
 
   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;
+    tm.insertChar( newParagraph, insertPos );
     position = 0;
   }
 
@@ -104,11 +88,9 @@
                               boolean requireNextWord)
   {
     int next = nextOffset( wrappingWidth, offsetLimit, requireNextWord );
-    AttributedCharacterIterator aci = (new AttributedString( text, 
-                                                            position, next )
-                                      ).getIterator();
+    TextLayout tl = tm.getLayout( position, next );
     position = next;
-    return new TextLayout( aci, frc );
+    return tl;
   }
 
   public int nextOffset(float wrappingWidth)
@@ -119,69 +101,40 @@
   public int nextOffset(float wrappingWidth, int offsetLimit, 
                        boolean requireNextWord)
   {
-    Shape s = totalLayout.getBlackBoxBounds( position, offsetLimit );
-    double remainingLength = s.getBounds2D().getWidth();
+    int guessOffset = tm.getLineBreakIndex(position, wrappingWidth);
+    if( offsetLimit > numChars )
+      offsetLimit = numChars;
 
-    int guessOffset = (int)( ( (double)wrappingWidth / (double)remainingLength)
-                            * ( (double)numChars - (double)position ) );
-    guessOffset += position;
     if( guessOffset > offsetLimit )
-      guessOffset = offsetLimit;
-
-    s = totalLayout.getBlackBoxBounds( position, guessOffset );
-    double guessLength = s.getBounds2D().getWidth();
-
-    boolean makeSmaller = ( guessLength > wrappingWidth );
-    int inc = makeSmaller ? -1 : 1;
-    boolean keepGoing = true;
-
-    do
-      {
-       guessOffset = guessOffset + inc;
-       if( guessOffset <= position || guessOffset > offsetLimit )
          {
-           keepGoing = false;
-         }
-       else
-         {
-           s = totalLayout.getBlackBoxBounds( position, guessOffset );
-           guessLength = s.getBounds2D().getWidth();
-           if( makeSmaller && ( guessLength <= wrappingWidth) )          
-             keepGoing = false;
-           if( !makeSmaller && ( guessLength >= wrappingWidth) )
-             keepGoing = false;
-         }
+       text.setIndex( offsetLimit );
+       return offsetLimit;
       }
-    while( keepGoing );
 
-    if( !makeSmaller )
-      guessOffset--;
+    text.setIndex( guessOffset );
 
-    if( guessOffset >= offsetLimit )
-      return offsetLimit;
+    // If we're on a breaking character, return directly
+    if( Character.isWhitespace( text.current() ) )
+      return guessOffset;
 
-    text.setIndex( guessOffset );
+    // Otherwise jump forward or backward to the last such char.
     if( !requireNextWord )
-      {
-       char c = text.previous();
-       while( !Character.isWhitespace( c ) && c != '-' && 
+      while( !Character.isWhitespace( text.previous() ) && 
               guessOffset > position )
-         { 
            guessOffset--; 
-           c = text.previous();
-         }
-      }
     else
-      {
-       char c = text.next();
-       while( !Character.isWhitespace( c ) && c != '-' && 
+      while( !Character.isWhitespace( text.next() ) && 
               guessOffset < offsetLimit )
-         {
            guessOffset++;
-           c = text.next();
-         }
+    
+    if( guessOffset > offsetLimit )
+      {
+       text.setIndex( offsetLimit );
+       return offsetLimit;
       }
 
+    text.setIndex( guessOffset );
+
     return guessOffset;
   }
 

Index: java/awt/font/TextLayout.java
===================================================================
RCS file: /sources/classpath/classpath/java/awt/font/TextLayout.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- java/awt/font/TextLayout.java       16 Jun 2006 15:14:56 -0000      1.12
+++ java/awt/font/TextLayout.java       18 Jun 2006 00:54:47 -0000      1.13
@@ -47,6 +47,7 @@
 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.Map;
@@ -71,6 +72,12 @@
   private int[][] runIndices;
 
   /**
+   * 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;
@@ -137,6 +144,7 @@
                                            Font.LAYOUT_LEFT_TO_RIGHT :
                                            Font.LAYOUT_RIGHT_TO_LEFT );
       }
+    setCharIndices();
   }
 
   public TextLayout (String string, Map attributes, FontRenderContext frc)  
@@ -145,9 +153,97 @@
   }
 
   public TextLayout (AttributedCharacterIterator text, FontRenderContext frc)
-    throws NotImplementedException
   {
-    throw new Error ("not implemented");
+    // 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)
+  {
+    font = t.font;
+    frc = t.frc;
+    boundsCache = null;
+    lm = t.lm;
+    leftToRight = t.leftToRight;
+
+    if( endIndex > t.getCharacterCount() )
+      endIndex = t.getCharacterCount();
+    string = t.string.substring( startIndex, endIndex );
+
+    int startingRun = t.charIndices[startIndex][0];
+    int nRuns = 1 + t.charIndices[endIndex - 1][0] - startingRun;
+    runIndices = new int[ nRuns ][2];
+
+    runs = new GlyphVector[ nRuns ];
+    for( int i = 0; i < nRuns; i++ )
+      {
+       GlyphVector run = t.runs[ i + startingRun ];
+       // 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) ? run.getNumGlyphs() : 
+         1 + t.charIndices[endIndex - 1][1] - beginGlyphIndex;
+       
+       int[] codes = run.getGlyphCodes(beginGlyphIndex, numEntries, null);
+       runs[ i ] = font.createGlyphVector( frc, codes );
+       runIndices[ i ][0] = t.runIndices[i + startingRun][0] - startIndex;
+       runIndices[ i ][1] = t.runIndices[i + startingRun][1] - startIndex;
+      }
+    runIndices[ nRuns - 1 ][1] = endIndex - 1;
+
+    setCharIndices();
+    determineWhiteSpace();
+  }
+
+  private void setCharIndices()
+  {
+    charIndices = new int[ getCharacterCount() ][2];
+    int i = 0;
+    int currentChar = 0;
+    for(int run = 0; run < runs.length; run++)
+      {
+       currentChar = -1;
+       for( int gi = 0; gi < runs[ run ].getNumGlyphs(); gi++)
+         {
+           if( runs[ run ].getGlyphCharIndex( gi ) != currentChar )
+             {
+               charIndices[ i ][0] = run;
+               charIndices[ i ][1] = gi;
+               currentChar = runs[ run ].getGlyphCharIndex( gi );
+               i++;
+             }
+         }
+      }
+  }
+
+  private static String getText(AttributedCharacterIterator iter)
+  {
+    StringBuffer sb = new StringBuffer();
+    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;
   }
 
   /**
@@ -177,10 +273,14 @@
          gotDirection = true;
          break;
        }
+    determineWhiteSpace();
+  }
 
+  private void determineWhiteSpace()
+  {
     // Determine if there's whitespace in the thing.
     // Ignore trailing chars.
-    i = string.length() - 1; 
+    int i = string.length() - 1; 
     hasWhitespace = false;
     while( i >= 0 && Character.isWhitespace( string.charAt(i) ) )
       i--;
@@ -249,56 +349,42 @@
 
   public Shape getBlackBoxBounds (int firstEndpoint, int secondEndpoint)
   {
-    if( firstEndpoint < 0 || secondEndpoint > getCharacterCount() )
+    if( secondEndpoint - firstEndpoint <= 0 )
+      return new Rectangle2D.Float(); // Hmm? 
+
+    if( firstEndpoint < 0 || secondEndpoint > getCharacterCount())
       return new Rectangle2D.Float();
 
     GeneralPath gp = new GeneralPath();
-    int i = 0; // run index
+    
+    int ri = charIndices[ firstEndpoint ][0];
+    int gi = charIndices[ firstEndpoint ][1];
+
     double advance = 0;
 
-    // go to first run
-    while( runIndices[i + 1][1] < firstEndpoint ) 
-      {
+    for( int i = 0; i < ri; i++ )
        advance += runs[i].getLogicalBounds().getWidth();
-       i++;
-      }
 
-    int j = 0; // index into the run.
-    if( runIndices[i][1] - runIndices[i][0] > 1 )
+    for( int i = ri; i <= charIndices[ secondEndpoint - 1 ][0]; i++ )
       {
-       while( runs[i].getGlyphCharIndex( j + 1 ) <
-              (firstEndpoint - runIndices[i][0] ) )j++;
-      }
-
-    gp.append(runs[i].getGlyphVisualBounds( j ), false);
-    boolean keepGoing = true;;
+       int dg;
+       if( i == charIndices[ secondEndpoint - 1 ][0] )
+         dg = charIndices[ secondEndpoint - 1][1];
+       else
+         dg = runs[i].getNumGlyphs() - 1;
 
-    do
-      {
-       while( j < runs[i].getNumGlyphs() && 
-              runs[i].getGlyphCharIndex( j ) + runIndices[i][0] < 
-              secondEndpoint )
+       for( int j = 0; j <= dg; j++ )
          {
            Rectangle2D r2 = (runs[i].getGlyphVisualBounds( j )).
              getBounds2D();
            Point2D p = runs[i].getGlyphPosition( j );
-           r2.setRect( advance + p.getX(), r2.getY(), 
+           r2.setRect( advance + r2.getX(), r2.getY(), 
                        r2.getWidth(), r2.getHeight() );
            gp.append(r2, false);
-           j++;
          }
 
-       if( j >= runs[i].getNumGlyphs() )
-         {
            advance += runs[i].getLogicalBounds().getWidth();
-           i++; 
-           j = 0;
-         }
-       else
-         keepGoing = false;
       }
-    while( keepGoing );
-
     return gp;
   }
 
@@ -382,55 +468,42 @@
   public Shape getLogicalHighlightShape (int firstEndpoint, int secondEndpoint,
                                          Rectangle2D bounds)
   {
-    if( firstEndpoint < 0 || secondEndpoint > getCharacterCount() )
+    if( secondEndpoint - firstEndpoint <= 0 )
+      return new Rectangle2D.Float(); // Hmm? 
+
+    if( firstEndpoint < 0 || secondEndpoint > getCharacterCount())
       return new Rectangle2D.Float();
 
-    int i = 0; // run index
+    Rectangle2D r = null;
+    int ri = charIndices[ firstEndpoint ][0];
+    int gi = charIndices[ firstEndpoint ][1];
+
     double advance = 0;
 
-    // go to first run
-    if( i > 0 )
-      while( runIndices[i + 1][1] < firstEndpoint ) 
-       {
+    for( int i = 0; i < ri; i++ )
          advance += runs[i].getLogicalBounds().getWidth();
-         i++;
-       }
 
-    int j = 0; // index into the run.
-    if( runIndices[i][1] - runIndices[i][0] > 1 )
+    for( int i = ri; i <= charIndices[ secondEndpoint - 1 ][0]; i++ )
       {
-       while( runs[i].getGlyphCharIndex( j + 1 ) <
-              (firstEndpoint - runIndices[i][0] ) )j++;
-      }
-
-    Rectangle2D r = (runs[i].getGlyphLogicalBounds( j )).getBounds2D();
-    boolean keepGoing = true;;
+       int dg; // last index in this run to use.
+       if( i == charIndices[ secondEndpoint - 1 ][0] )
+         dg = charIndices[ secondEndpoint - 1][1];
+       else
+         dg = runs[i].getNumGlyphs() - 1;
 
-    do
+       for(; gi <= dg; gi++ )
       {
-       while( j < runs[i].getNumGlyphs() && 
-              runs[i].getGlyphCharIndex( j ) + runIndices[i][0] < 
-              secondEndpoint )
-         {
-           Rectangle2D r2 = (runs[i].getGlyphLogicalBounds( j )).
+           Rectangle2D r2 = (runs[i].getGlyphLogicalBounds( gi )).
              getBounds2D();
-           Point2D p = runs[i].getGlyphPosition( j );
-           r2.setRect( advance + p.getX(), r2.getY(), 
-                       r2.getWidth(), r2.getHeight() );
-           r = r.createUnion( r2 );
-           j++;
+           if( r == null )
+             r = r2;
+           else
+             r = r.createUnion(r2);
          }
+       gi = 0; // reset glyph index into run for next run.
 
-       if( j >= runs[i].getNumGlyphs() )
-         {
            advance += runs[i].getLogicalBounds().getWidth();
-           i++; 
-           j = 0;
-         }
-       else
-         keepGoing = false;
       }
-    while( keepGoing );
 
     return r;
   }

Index: java/awt/font/TextMeasurer.java
===================================================================
RCS file: /sources/classpath/classpath/java/awt/font/TextMeasurer.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- java/awt/font/TextMeasurer.java     22 Mar 2006 19:15:24 -0000      1.3
+++ java/awt/font/TextMeasurer.java     18 Jun 2006 00:54:47 -0000      1.4
@@ -38,67 +38,156 @@
 
 package java.awt.font;
 
-import gnu.classpath.NotImplementedException;
-
 import java.text.AttributedCharacterIterator;
+import java.text.AttributedString;
+import java.awt.Shape;
 
 /**
- * @author Michael Koch
+ * 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 ci;
+  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.ci = text;
+    this.text = text;
     this.frc = frc;
+    totalLayout = new TextLayout( text, frc );
+    numChars = totalLayout.getCharacterCount();
   }
 
+  /**
+   * Clones the TextMeasurer object
+   */
   protected Object clone ()
   {
-    try
-      {
-        return super.clone ();
-      }
-    catch (CloneNotSupportedException e)
-      {
-        // This may never occur
-        throw new InternalError ();
-      }
+    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)
-    throws NotImplementedException
   {
-    throw new Error ("not implemented");
+    totalLayout = new TextLayout(newParagraph, frc);
+    if( deletePos < 0 || deletePos > totalLayout.getCharacterCount() )
+      throw new NullPointerException("Invalid deletePos:"+deletePos);
+    numChars = totalLayout.getCharacterCount();
+    text = newParagraph;
   }
 
-  public float getAdvanceBetween (int start, int limit)
-    throws NotImplementedException
+  /**
+   * 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)
   {
-    throw new Error ("not implemented");
+    totalLayout = new TextLayout(newParagraph, frc);
+    if( insertPos < 0 || insertPos > totalLayout.getCharacterCount() )
+      throw new NullPointerException("Invalid insertPos:"+insertPos);
+    numChars = totalLayout.getCharacterCount();
+    text = newParagraph;
   }
 
-  public TextLayout getLayout (int start, int limit)
-    throws NotImplementedException
+  /***
+   * 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)
   {
-    throw new Error ("not implemented");
+    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)
+  {
+//     AttributedCharacterIterator aci = (new AttributedString( text, 
+//                                                          start, limit
+//                                                          ) ).getIterator();
+//     return new TextLayout( aci, frc );
+    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)
-    throws NotImplementedException
   {
-    throw new Error ("not implemented");
-  }
+    if( start < 0 )
+      throw new IllegalArgumentException("Start parameter must be > 0.");
 
-  public void insertChar (AttributedCharacterIterator newParagraph,
-                          int insertPos)
-    throws NotImplementedException
+    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
   {
-    throw new Error ("not implemented");
+       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;
   }
 }

Index: java/text/AttributedString.java
===================================================================
RCS file: /sources/classpath/classpath/java/text/AttributedString.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- java/text/AttributedString.java     24 Oct 2005 10:04:22 -0000      1.15
+++ java/text/AttributedString.java     18 Jun 2006 00:54:47 -0000      1.16
@@ -221,16 +221,13 @@
             // If the attribute run starts before the beginning index, we
             // need to junk it if it is an Annotation.
             Object attrib_obj = aci.getAttribute(attrib);
-            if (rs < begin)
+           rs -= begin;
+            if (rs < 0)
               {
                 if (attrib_obj instanceof Annotation)
                    continue;
 
-                rs = begin;
-              }
-            else
-              {
-                rs -= begin;
+                rs = 0;
               }
 
             // Create a map object.  Yes this will only contain one attribute
@@ -243,7 +240,7 @@
 
         c = aci.next();
       }
-    while(c != CharacterIterator.DONE);
+    while( aci.getIndex() < end );
 
     attribs = new AttributeRange[accum.size()];
     attribs = (AttributeRange[]) accum.toArray(attribs);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]