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: Fri, 09 Jun 2006 20:23:55 +0000

CVSROOT:        /sources/classpath
Module name:    classpath
Changes by:     Sven de Marothy <smarothy>      06/06/09 20:23:55

Modified files:
        .              : ChangeLog 
        gnu/java/awt/peer/gtk: FreetypeGlyphVector.java GdkFontPeer.java 
        java/awt/font  : TextLayout.java 
        java/text      : Bidi.java 

Log message:
        2006-06-08  Sven de Marothy  <address@hidden>
        
                * java/text/Bidi.java: Treat WS as neutral for rules N1 & N2.
                * gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
                New constructor for bidirectionality.
                (getGlyphMetrics): Return whitespace glyphs.
                (getLogicalBounds): Offset rectangles to correct positions.
                * gnu/java/awt/peer/gtk/GdkFontPeer.java
                (getBaselineFor): Default to ROMAN_BASELINE.
                (GdkFontLineMetrics): Guess some values for underline and 
                strikethrough.
                (layoutGlyphVector): Use bidirectionality.
                * java/awt/font/TextLayout.java: Implement, mostly.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/classpath/ChangeLog?cvsroot=classpath&r1=1.7743&r2=1.7744
http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java?cvsroot=classpath&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java?cvsroot=classpath&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/classpath/java/awt/font/TextLayout.java?cvsroot=classpath&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/classpath/java/text/Bidi.java?cvsroot=classpath&r1=1.5&r2=1.6

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/classpath/classpath/ChangeLog,v
retrieving revision 1.7743
retrieving revision 1.7744
diff -u -b -r1.7743 -r1.7744
--- ChangeLog   9 Jun 2006 17:02:31 -0000       1.7743
+++ ChangeLog   9 Jun 2006 20:23:54 -0000       1.7744
@@ -1,3 +1,17 @@
+2006-06-08  Sven de Marothy  <address@hidden>
+
+       * java/text/Bidi.java: Treat WS as neutral for rules N1 & N2.
+       * gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
+       New constructor for bidirectionality.
+       (getGlyphMetrics): Return whitespace glyphs.
+       (getLogicalBounds): Offset rectangles to correct positions.
+       * gnu/java/awt/peer/gtk/GdkFontPeer.java
+       (getBaselineFor): Default to ROMAN_BASELINE.
+       (GdkFontLineMetrics): Guess some values for underline and 
+       strikethrough.
+       (layoutGlyphVector): Use bidirectionality.
+       * java/awt/font/TextLayout.java: Implement, mostly.
+       
 2006-06-09  Anthony Green  <address@hidden>
 
        PR classpath/27888:

Index: gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
===================================================================
RCS file: 
/sources/classpath/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- gnu/java/awt/peer/gtk/FreetypeGlyphVector.java      7 Jun 2006 23:48:05 
-0000       1.3
+++ gnu/java/awt/peer/gtk/FreetypeGlyphVector.java      9 Jun 2006 20:23:55 
-0000       1.4
@@ -82,10 +82,25 @@
   private AffineTransform[] glyphTransforms;
 
   /**
+   * Keep track of which glyphs are whitespace, since we don't have
+   * reporting from the peers yet. TextLayout needs this for justification.
+   */
+  private boolean[] whiteSpace;
+
+  /**
    * Create a glyphvector from a given (Freetype) font and a String.
    */
   public FreetypeGlyphVector(Font f, String s, FontRenderContext frc)
   {
+    this(f, s, frc, Font.LAYOUT_LEFT_TO_RIGHT);
+  }
+
+  /**
+   * Create a glyphvector from a given (Freetype) font and a String.
+   */
+  public FreetypeGlyphVector(Font f, String s, FontRenderContext frc,
+                            int flags)
+  {
     this.s = s;
     this.font = f;
     this.frc = frc;
@@ -94,6 +109,14 @@
     peer = (GdkFontPeer)font.getPeer();
 
     getGlyphs();
+    if( flags == Font.LAYOUT_RIGHT_TO_LEFT )
+      {
+       // reverse the glyph ordering.
+       int[] temp = new int[ nGlyphs ];
+       for(int i = 0; i < nGlyphs; i++)
+         temp[ i ] = glyphCodes[ nGlyphs - i - 1];
+       glyphCodes = temp;
+      }
     performDefaultLayout();
   }
 
@@ -180,10 +203,12 @@
    */
   public void performDefaultLayout()
   {
+    whiteSpace = new boolean[ nGlyphs ]; 
     glyphTransforms = new AffineTransform[ nGlyphs ]; 
     double x = 0;
     for(int i = 0; i < nGlyphs; i++)
       {
+       whiteSpace[i] = Character.isWhitespace( glyphCodes[ i ] );
        GlyphMetrics gm = getGlyphMetrics( i );
        Rectangle2D r = gm.getBounds2D();
        glyphTransforms[ i ] = AffineTransform.getTranslateInstance(x, 0);
@@ -237,17 +262,20 @@
 
   /**
    * Returns the metrics of a single glyph.
+   * FIXME: Not all glyph types are supported.
    */
   public GlyphMetrics getGlyphMetrics(int glyphIndex)
   {
     double[] val = getMetricsNative( glyphCodes[ glyphIndex ] );
     if( val == null )
       return null;
+    byte type = whiteSpace[ glyphIndex ] ? 
+      GlyphMetrics.WHITESPACE : GlyphMetrics.STANDARD;
     
     return new GlyphMetrics( true, (float)val[1], (float)val[2], 
                             new Rectangle2D.Double( val[3], val[4], 
                                                     val[5], val[6] ),
-                            GlyphMetrics.STANDARD );
+                            type );
   }
 
   /**
@@ -319,7 +347,12 @@
 
     Rectangle2D rect = (Rectangle2D)getGlyphLogicalBounds( 0 );
     for( int i = 1; i < nGlyphs; i++ )
-      rect = rect.createUnion( (Rectangle2D)getGlyphLogicalBounds( i ) );
+      {
+       Rectangle2D r2 = (Rectangle2D)getGlyphLogicalBounds( i );
+       Point2D p = getGlyphPosition( i );
+       r2.setRect( p.getX(), p.getY(), r2.getWidth(), r2.getHeight() );
+       rect = rect.createUnion( r2 );
+      }
 
     return rect;
   }

Index: gnu/java/awt/peer/gtk/GdkFontPeer.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- gnu/java/awt/peer/gtk/GdkFontPeer.java      7 Jun 2006 13:54:32 -0000       
1.15
+++ gnu/java/awt/peer/gtk/GdkFontPeer.java      9 Jun 2006 20:23:55 -0000       
1.16
@@ -252,18 +252,24 @@
 
   public byte getBaselineFor (Font font, char c)
   {
-    throw new UnsupportedOperationException ();
+    // FIXME: Actually check.
+    return Font.ROMAN_BASELINE;
   }
 
-  protected class GdkFontLineMetrics extends LineMetrics
+  private static class GdkFontLineMetrics extends LineMetrics
   {
-    FontMetrics fm;
-    int nchars; 
+    private FontMetrics fm;
+    private int nchars; 
+    private float strikethroughOffset, strikethroughThickness,
+      underlineOffset, underlineThickness;
 
-    public GdkFontLineMetrics (FontMetrics m, int n)
+    public GdkFontLineMetrics (GdkFontPeer fp, FontMetrics m, int n)
     {
       fm = m;
       nchars = n;
+      strikethroughOffset = 0f;
+      strikethroughThickness = underlineThickness = ((float)fp.size) / 12f;
+      underlineOffset = 0f;
     }
 
     public float getAscent()
@@ -273,6 +279,7 @@
   
     public int getBaselineIndex()
     {
+      // FIXME
       return Font.ROMAN_BASELINE;
     }
     
@@ -303,7 +310,7 @@
   public LineMetrics getLineMetrics (Font font, CharacterIterator ci, 
                                      int begin, int limit, FontRenderContext 
rc)
   {
-    return new GdkFontLineMetrics (getFontMetrics (font), limit - begin);
+    return new GdkFontLineMetrics (this, getFontMetrics (font), limit - begin);
   }
 
   public Rectangle2D getMaxCharBounds (Font font, FontRenderContext rc)
@@ -350,20 +357,15 @@
                                         char[] chars, int start, int limit, 
                                         int flags)
   {
-    int nchars = (limit - start) + 1;
-    char[] nc = new char[nchars];
-
-    for (int i = 0; i < nchars; ++i)
-      nc[i] = chars[start + i];
-
-    return createGlyphVector (font, frc, 
-                              new StringCharacterIterator (new String (nc)));
+    return new FreetypeGlyphVector( font, new String( chars, start, 
+                                                     limit - start),
+                                   frc, flags);
   }
 
   public LineMetrics getLineMetrics (Font font, String str, 
                                      FontRenderContext frc)
   {
-    return new GdkFontLineMetrics (getFontMetrics (font), str.length ());
+    return new GdkFontLineMetrics (this, getFontMetrics (font), str.length ());
   }
 
   public FontMetrics getFontMetrics (Font font)

Index: java/awt/font/TextLayout.java
===================================================================
RCS file: /sources/classpath/classpath/java/awt/font/TextLayout.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- java/awt/font/TextLayout.java       2 Jul 2005 20:32:29 -0000       1.7
+++ java/awt/font/TextLayout.java       9 Jun 2006 20:23:55 -0000       1.8
@@ -1,5 +1,5 @@
 /* TextLayout.java --
-   Copyright (C) 2003, 2004  Free Software Foundation, Inc.
+   Copyright (C) 2006  Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -38,8 +38,7 @@
 
 package java.awt.font;
 
-import gnu.java.awt.ClasspathToolkit;
-import gnu.java.awt.peer.ClasspathTextLayoutPeer;
+import gnu.classpath.NotImplementedException;
 
 import java.awt.Font;
 import java.awt.Graphics2D;
@@ -47,116 +46,269 @@
 import java.awt.Toolkit;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Rectangle2D;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
 import java.text.AttributedCharacterIterator;
 import java.text.AttributedString;
+import java.text.Bidi;
 import java.util.Map;
 
 /**
- * @author Michael Koch
+ * @author Sven de Marothy
  */
 public final class TextLayout implements Cloneable
 {
-  public static final CaretPolicy DEFAULT_CARET_POLICY = new CaretPolicy ();
-  ClasspathTextLayoutPeer peer;
+  private GlyphVector[] runs;
+  private Font font;
+  private FontRenderContext frc;
+  private String string;
+  private Rectangle2D boundsCache;
+  private LineMetrics lm;
+
+  /**
+   * Start and end character indices of the runs.
+   * First index is the run number, second is 0 or 1 for the starting 
+   * and ending character index of the run, respectively.
+   */
+  private int[][] runIndices;
 
-  public static class CaretPolicy
-  {
-    public CaretPolicy ()
-    {
-      // Do nothing here.
-    }
+  /**
+   * Base directionality, determined from the first char.
+   */
+  private boolean leftToRight;
 
-    public TextHitInfo getStrongCaret (TextHitInfo hit1, TextHitInfo hit2,
-                                       TextLayout layout)
+  /**
+   * Whether this layout contains whitespace or not.
+   */
+  private boolean hasWhitespace = false;
+
+  /**
+   * The default caret policy.
+   */
+  static TextLayout.CaretPolicy DEFAULT_CARET_POLICY = new CaretPolicy();
+
+  /**
+   * Constructs a TextLayout.
+   */
+  public TextLayout (String string, Font font, FontRenderContext frc) 
     {
-      return layout.peer.getStrongCaret(hit1, hit2);
+    this.font = font;
+    this.frc = frc;
+    this.string = string;
+    lm = font.getLineMetrics(string, frc);
+
+    // Get base direction and whitespace info
+    getStringProperties();
+
+    if( Bidi.requiresBidi( string.toCharArray(), 0, string.length() ) )
+      {
+       Bidi bidi = new Bidi( string, 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 GlyphVector[ rc ];
+       runIndices = new int[rc][2];
+       for(int i = 0; i < runs.length; i++)
+         {
+           runIndices[i][0] = bidi.getRunStart( i );
+           runIndices[i][1] = bidi.getRunLimit( i );
+           if( runIndices[i][0] != runIndices[i][1] ) // no empty runs.
+             {
+               runs[i] = font.layoutGlyphVector
+                 ( frc, string.toCharArray(),
+                   runIndices[i][0], runIndices[i][1],
+                   ((table[i] & 1) == 0) ? Font.LAYOUT_LEFT_TO_RIGHT :
+                   Font.LAYOUT_RIGHT_TO_LEFT );
+             }
+         }
+       Bidi.reorderVisually( table, 0, runs, 0, runs.length );
+      }
+    else
+      {
+       runs = new GlyphVector[ 1 ];
+       runIndices = new int[1][2];
+       runIndices[0][0] = 0;
+       runIndices[0][1] = string.length();
+       runs[ 0 ] = font.layoutGlyphVector( frc, string.toCharArray(), 
+                                           0, string.length(),
+                                           leftToRight ?
+                                           Font.LAYOUT_LEFT_TO_RIGHT :
+                                           Font.LAYOUT_RIGHT_TO_LEFT );
     }
   }
 
-  public TextLayout (AttributedCharacterIterator text, FontRenderContext frc)
+  public TextLayout (String string, Map attributes, FontRenderContext frc)  
   {    
-    AttributedString as = new AttributedString (text);
-    ClasspathToolkit tk = (ClasspathToolkit)(Toolkit.getDefaultToolkit ());
-    peer = tk.getClasspathTextLayoutPeer(as, frc);
+    this( string, new Font( attributes ), frc );
   }
 
-  public TextLayout (String string, Font font, FontRenderContext frc) 
+  public TextLayout (AttributedCharacterIterator text, FontRenderContext frc)
+    throws NotImplementedException
   {
-    AttributedString as = new AttributedString (string);
-    as.addAttribute (TextAttribute.FONT, font);
-    ClasspathToolkit tk = (ClasspathToolkit)(Toolkit.getDefaultToolkit ());
-    peer = tk.getClasspathTextLayoutPeer(as, frc);
+    throw new Error ("not implemented");
   }
 
-  public TextLayout (String string, Map attributes, FontRenderContext frc)  
+  /**
+   * Scan the character run for the first strongly directional character,
+   * which in turn defines the base directionality of the whole layout.
+   */
+  private void getStringProperties()
   {
-    AttributedString as = new AttributedString (string, attributes);
-    ClasspathToolkit tk = (ClasspathToolkit)(Toolkit.getDefaultToolkit ());
-    peer = tk.getClasspathTextLayoutPeer(as, frc);
+    boolean gotDirection = false;
+    int i = 0;
+
+    leftToRight = true;
+    while( i < string.length() && !gotDirection )
+      switch( Character.getDirectionality( string.charAt( 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;
+       }
+
+    // Determine if there's whitespace in the thing.
+    // Ignore trailing chars.
+    i = string.length() - 1; 
+    hasWhitespace = false;
+    while( i >= 0 && Character.isWhitespace( string.charAt(i) ) )
+      i--;
+    // Check the remaining chars
+    while( i >= 0 )
+      if( Character.isWhitespace( string.charAt(i--) ) )
+       hasWhitespace = true;
   }
 
   protected Object clone ()
   {
-    try
-      {
-        TextLayout tl = (TextLayout) super.clone ();
-        tl.peer = (ClasspathTextLayoutPeer) this.peer.clone();
-        return tl;
+    return new TextLayout( string, font, frc );
       }
-    catch (CloneNotSupportedException e)
-      {
-        // This should never occur
-        throw new InternalError ();
-      }
-  }
-
 
   public void draw (Graphics2D g2, float x, float y) 
   {
-    peer.draw(g2, x, y);
+    for(int i = 0; i < runs.length; i++)
+      {
+       g2.drawGlyphVector(runs[i], x, y);
+       Rectangle2D r = runs[i].getLogicalBounds();
+       x += r.getWidth();
+      }
   }
 
   public boolean equals (Object obj)
   {
-    if (! (obj instanceof TextLayout))
+    if( !( obj instanceof TextLayout) )
       return false;
 
-    return equals ((TextLayout) obj);
+    return equals( (TextLayout) obj );
   }
 
   public boolean equals (TextLayout tl)
   {
-    return this.peer.equals(tl.peer);
+    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 ()
   {
-    return peer.getAdvance();
+    float totalAdvance = 0f;
+    for(int i = 0; i < runs.length; i++)
+      totalAdvance += runs[i].getLogicalBounds().getWidth();
+    return totalAdvance;
   }
 
   public float getAscent ()
   {
-    return peer.getAscent();
+    return lm.getAscent();
   }
 
   public byte getBaseline ()
   {
-    return peer.getBaseline();
+    return (byte)lm.getBaselineIndex();
   }
 
   public float[] getBaselineOffsets ()
   {
-    return peer.getBaselineOffsets();
+    return lm.getBaselineOffsets();
   }
 
   public Shape getBlackBoxBounds (int firstEndpoint, int secondEndpoint)
   {
-    return peer.getBlackBoxBounds(firstEndpoint, secondEndpoint);
+    if( firstEndpoint < 0 || secondEndpoint > getCharacterCount() )
+      return new Rectangle2D.Float();
+
+    GeneralPath gp = new GeneralPath();
+    int i = 0; // run index
+    double advance = 0;
+
+    // go to first run
+    while( runIndices[i + 1][1] < firstEndpoint ) 
+      {
+       advance += runs[i].getLogicalBounds().getWidth();
+       i++;
+      }
+
+    int j = 0; // index into the run.
+    if( runIndices[i][1] - runIndices[i][0] > 1 )
+      {
+       while( runs[i].getGlyphCharIndex( j + 1 ) <
+              (firstEndpoint - runIndices[i][0] ) )j++;
+      }
+
+    gp.append(runs[i].getGlyphVisualBounds( j ), false);
+    boolean keepGoing = true;;
+
+    do
+      {
+       while( j < runs[i].getNumGlyphs() && 
+              runs[i].getGlyphCharIndex( j ) + runIndices[i][0] < 
+              secondEndpoint )
+         {
+           Rectangle2D r2 = (runs[i].getGlyphVisualBounds( j )).
+             getBounds2D();
+           Point2D p = runs[i].getGlyphPosition( j );
+           r2.setRect( advance + p.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;
   }
 
   public Rectangle2D getBounds()
   {
-    return peer.getBounds();
+    if( boundsCache == null )
+      boundsCache = getOutline(new AffineTransform()).getBounds();
+    return boundsCache;
   }
 
   public float[] getCaretInfo (TextHitInfo hit)
@@ -165,144 +317,272 @@
   }
 
   public float[] getCaretInfo (TextHitInfo hit, Rectangle2D bounds)
+    throws NotImplementedException
   {
-    return peer.getCaretInfo(hit, bounds);
+    throw new Error ("not implemented");
   }
 
   public Shape getCaretShape (TextHitInfo hit)
   {
-    return getCaretShape(hit, getBounds());
+    return getCaretShape( hit, getBounds() );
   }
 
   public Shape getCaretShape (TextHitInfo hit, Rectangle2D bounds)
+    throws NotImplementedException
   {
-    return peer.getCaretShape(hit, bounds);
+    throw new Error ("not implemented");
   }
 
   public Shape[] getCaretShapes (int offset)
   {
-    return getCaretShapes(offset, getBounds());
+    return getCaretShapes( offset, getBounds() );
   }
 
   public Shape[] getCaretShapes (int offset, Rectangle2D bounds)
+    throws NotImplementedException
   {
-    return getCaretShapes(offset, getBounds(), DEFAULT_CARET_POLICY);
-  }
-
-  public Shape[] getCaretShapes (int offset, Rectangle2D bounds,
-                                 TextLayout.CaretPolicy policy)
-  {
-    return peer.getCaretShapes(offset, bounds, policy);
+    throw new Error ("not implemented");
   }
 
   public int getCharacterCount ()
   {
-    return peer.getCharacterCount();
+    return string.length();
   }
 
   public byte getCharacterLevel (int index)
+    throws NotImplementedException
   {
-    return peer.getCharacterLevel(index);
+    throw new Error ("not implemented");
   }
 
   public float getDescent ()
   {
-    return peer.getDescent();
+    return lm.getDescent();
   }
 
   public TextLayout getJustifiedLayout (float justificationWidth)
   {
-    return peer.getJustifiedLayout(justificationWidth);
+    TextLayout newLayout = (TextLayout)clone();
+
+    if( hasWhitespace )
+      newLayout.handleJustify( justificationWidth );
+
+    return newLayout;
   }
 
   public float getLeading ()
   {
-    return peer.getLeading();
+    return lm.getLeading();
   }
 
   public Shape getLogicalHighlightShape (int firstEndpoint, int secondEndpoint)
   {
-    return getLogicalHighlightShape (firstEndpoint, secondEndpoint, 
getBounds());
+    return getLogicalHighlightShape( firstEndpoint, secondEndpoint, 
+                                    getBounds() );
   }
 
   public Shape getLogicalHighlightShape (int firstEndpoint, int secondEndpoint,
                                          Rectangle2D bounds)
   {
-    return peer.getLogicalHighlightShape(firstEndpoint, secondEndpoint, 
bounds);
+    if( firstEndpoint < 0 || secondEndpoint > getCharacterCount() )
+      return new Rectangle2D.Float();
+
+    int i = 0; // run index
+    double advance = 0;
+
+    // go to first run
+    while( runIndices[i + 1][1] < firstEndpoint ) 
+      {
+       advance += runs[i].getLogicalBounds().getWidth();
+       i++;
   }
 
-  public int[] getLogicalRangesForVisualSelection (TextHitInfo firstEndpoint,
-                                                   TextHitInfo secondEndpoint)
+    int j = 0; // index into the run.
+    if( runIndices[i][1] - runIndices[i][0] > 1 )
   {
-    return peer.getLogicalRangesForVisualSelection(firstEndpoint, 
secondEndpoint);
+       while( runs[i].getGlyphCharIndex( j + 1 ) <
+              (firstEndpoint - runIndices[i][0] ) )j++;
   }
 
-  public TextHitInfo getNextLeftHit (int offset)
+    Rectangle2D r = (runs[i].getGlyphLogicalBounds( j )).getBounds2D();
+    boolean keepGoing = true;;
+
+    do
+      {
+       while( j < runs[i].getNumGlyphs() && 
+              runs[i].getGlyphCharIndex( j ) + runIndices[i][0] < 
+              secondEndpoint )
   {
-    return getNextLeftHit(offset, DEFAULT_CARET_POLICY);
+           Rectangle2D r2 = (runs[i].getGlyphLogicalBounds( j )).
+             getBounds2D();
+           Point2D p = runs[i].getGlyphPosition( j );
+           r2.setRect( advance + p.getX(), r2.getY(), 
+                       r2.getWidth(), r2.getHeight() );
+           r = r.createUnion( r2 );
+           j++;
   }
 
-  public TextHitInfo getNextLeftHit (int offset, TextLayout.CaretPolicy policy)
+       if( j >= runs[i].getNumGlyphs() )
   {
-    return peer.getNextLeftHit(offset, policy);
+           advance += runs[i].getLogicalBounds().getWidth();
+           i++; 
+           j = 0;
   }
+       else
+         keepGoing = false;
+      }
+    while( keepGoing );
 
-  public TextHitInfo getNextLeftHit (TextHitInfo hit)
+    return r;
+  }
+
+  public int[] getLogicalRangesForVisualSelection (TextHitInfo firstEndpoint,
+                                                   TextHitInfo secondEndpoint)
+    throws NotImplementedException
   {
-    return getNextLeftHit(hit.getCharIndex());
+    throw new Error ("not implemented");
   }
 
-  public TextHitInfo getNextRightHit (int offset)
+  public TextHitInfo getNextLeftHit (int offset)
+    throws NotImplementedException
   {
-    return getNextRightHit(offset, DEFAULT_CARET_POLICY);
+    throw new Error ("not implemented");
   }
 
-  public TextHitInfo getNextRightHit (int offset, TextLayout.CaretPolicy 
policy)
+  public TextHitInfo getNextLeftHit (TextHitInfo hit)
+    throws NotImplementedException
   {
-    return peer.getNextRightHit(offset, policy);
+    throw new Error ("not implemented");
+  }
+
+  public TextHitInfo getNextRightHit (int offset)
+    throws NotImplementedException
+  {
+    throw new Error ("not implemented");
   }
 
   public TextHitInfo getNextRightHit (TextHitInfo hit)
+    throws NotImplementedException
   {
-    return getNextRightHit(hit.getCharIndex());
+    throw new Error ("not implemented");
   }
 
   public Shape getOutline (AffineTransform tx)
   {
-    return peer.getOutline(tx);
+    float x = 0f;
+    GeneralPath gp = new GeneralPath();
+    for(int i = 0; i < runs.length; i++)
+      {
+       gp.append( runs[i].getOutline( x, 0f ), false );
+       Rectangle2D r = runs[i].getLogicalBounds();
+       x += r.getWidth();
+      }
+    gp.transform( tx );
+    return gp;
   }
 
   public float getVisibleAdvance ()
   {
-    return peer.getVisibleAdvance();
+    float totalAdvance = 0f;
+
+    if( runs.length <= 0 )
+      return 0f;
+
+    // No trailing whitespace
+    if( !Character.isWhitespace( string.charAt( string.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].getLogicalBounds().getWidth();
+
+    int lastRun = runIndices[ runs.length - 1 ][0];
+    int j = string.length() - 1;
+    while( j >= lastRun && Character.isWhitespace( string.charAt( j ) ) ) j--;
+
+    if( j < lastRun )
+      return totalAdvance; // entire last run is whitespace
+
+    int lastNonWSChar = j - lastRun;
+    j = 0;
+    while( runs[ runs.length - 1 ].getGlyphCharIndex( j )
+          <= lastNonWSChar )
+      {
+       totalAdvance += runs[ runs.length - 1 ].getGlyphLogicalBounds( j ).
+         getBounds2D().getWidth();
+       j ++;
+      }
+    
+    return totalAdvance;
   }
 
   public Shape getVisualHighlightShape (TextHitInfo firstEndpoint,
                                         TextHitInfo secondEndpoint)
   {
-    return getVisualHighlightShape(firstEndpoint, secondEndpoint, getBounds());
+    return getVisualHighlightShape( firstEndpoint, secondEndpoint, 
+                                   getBounds() );
   }
 
   public Shape getVisualHighlightShape (TextHitInfo firstEndpoint,
                                         TextHitInfo secondEndpoint,
                                         Rectangle2D bounds)
+    throws NotImplementedException
   {
-    return peer.getVisualHighlightShape(firstEndpoint, secondEndpoint, bounds);
+    throw new Error ("not implemented");
   }
 
   public TextHitInfo getVisualOtherHit (TextHitInfo hit)
+    throws NotImplementedException
   {
-    return peer.getVisualOtherHit(hit);
+    throw new Error ("not implemented");
   }
 
+  /**
+   * This is a protected method of a <code>final</code> class, meaning
+   * it exists only to taunt you.
+   */
   protected void handleJustify (float justificationWidth)
   {
-    peer.handleJustify(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 = string.length() - 1;
+    while( Character.isWhitespace( string.charAt( lastNWS ) ) ) lastNWS--;
+
+    // locations of the glyphs.
+    int[] wsglyphs = new int[string.length() * 10];
+    for(int run = 0; run < runs.length; run++ )
+      for(int i = 0; i < runs[run].getNumGlyphs(); i++ )
+       {
+         int cindex = runIndices[run][0] + runs[run].getGlyphCharIndex( i );
+         if( Character.isWhitespace( string.charAt( cindex ) ) )
+           //        && cindex < lastNWS )
+           {
+             wsglyphs[ nglyphs * 2 ] = run;
+             wsglyphs[ nglyphs * 2 + 1] = i;
+             nglyphs++;
+           }
   }
 
-  public int hashCode ()
+    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++ )
+      for(int i = 0; i < runs[ run ].getNumGlyphs(); i++ )
   {
-    return peer.hashCode();
+         if( wsglyphs[ cws * 2 ] == run && wsglyphs[ cws * 2 + 1 ] == i )
+           {
+             cws++; // update 'current whitespace'
+             w += deltaW; // increment the shift
+           }
+         Point2D p = runs[ run ].getGlyphPosition( i );
+         p.setLocation( p.getX() + w, p.getY() );
+         runs[ run ].setGlyphPosition( i, p );
+       }
   }
 
   public TextHitInfo hitTestChar (float x, float y)
@@ -312,21 +592,48 @@
 
   public TextHitInfo hitTestChar (float x, float y, Rectangle2D bounds)
   {
-    return peer.hitTestChar(x, y, bounds);
+    return hitTestChar( x, y, getBounds() );
   }
 
   public boolean isLeftToRight ()
   {
-    return peer.isLeftToRight();
+    return leftToRight;
   }
 
   public boolean isVertical ()
   {
-    return peer.isVertical();
+    return false; // FIXME: How do you create a vertical layout?
+  }
+
+  public int hashCode ()
+    throws NotImplementedException
+  {
+    throw new Error ("not implemented");
   }
 
   public String toString ()
   {
-    return peer.toString();
+    return "TextLayout [string:"+string+", Font:"+font+" Rendercontext:"+
+      frc+"]";
+  }
+
+  /**
+   * Inner class describing a caret policy
+   */
+  public static class CaretPolicy
+  {
+    public CaretPolicy()
+    {
+    }
+
+    public TextHitInfo getStrongCaret(TextHitInfo hit1,
+                                     TextHitInfo hit2,
+                                     TextLayout layout)
+      throws NotImplementedException
+    {
+      throw new Error ("not implemented");
+    }
   }
 }
+
+

Index: java/text/Bidi.java
===================================================================
RCS file: /sources/classpath/classpath/java/text/Bidi.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- java/text/Bidi.java 8 Jun 2006 23:32:13 -0000       1.5
+++ java/text/Bidi.java 9 Jun 2006 20:23:55 -0000       1.6
@@ -644,6 +644,7 @@
               case Character.DIRECTIONALITY_OTHER_NEUTRALS:
               case Character.DIRECTIONALITY_SEGMENT_SEPARATOR:
               case Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR:
+             case Character.DIRECTIONALITY_WHITESPACE:
                 if (neutralStart == -1)
                   neutralStart = i;
                 break;




reply via email to

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