OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / java / awt / peer / gtk / FreetypeGlyphVector.java
index 2c9d917..131a964 100644 (file)
@@ -39,14 +39,15 @@ package gnu.java.awt.peer.gtk;
 
 import java.awt.Font;
 import java.awt.Shape;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.GeneralPath;
+import java.awt.font.FontRenderContext;
 import java.awt.font.GlyphJustificationInfo;
 import java.awt.font.GlyphMetrics;
 import java.awt.font.GlyphVector;
-import java.awt.font.FontRenderContext;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.Arrays;
 
 public class FreetypeGlyphVector extends GlyphVector
 {
@@ -91,16 +92,17 @@ public class FreetypeGlyphVector extends GlyphVector
    */
   public FreetypeGlyphVector(Font f, String s, FontRenderContext frc)
   {
-    this(f, s, frc, Font.LAYOUT_LEFT_TO_RIGHT);
+    this(f, s.toCharArray(), 0, s.length(), 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)
+  public FreetypeGlyphVector(Font f, char[] chars, int start, int len,
+                             FontRenderContext frc, int flags)
   {
-    this.s = s;
+    this.s = new String(chars, start, len);
+
     this.font = f;
     this.frc = frc;
     if( !(font.getPeer() instanceof GdkFontPeer ) )
@@ -155,14 +157,15 @@ public class FreetypeGlyphVector extends GlyphVector
       }
 
     glyphCodes = new int[ nGlyphs ];
-    glyphPositions = new float[ nGlyphs ];
+    glyphPositions = new float[(nGlyphs + 1) * 2];
     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 ];
+        glyphTransforms[ i ] = new AffineTransform( gv.glyphTransforms[ i ] );
+        glyphCodes[i] = gv.glyphCodes[ i ];
       }
+    System.arraycopy(gv.glyphPositions, 0, glyphPositions, 0,
+                     glyphPositions.length);
   }
 
   /**
@@ -178,10 +181,17 @@ public class FreetypeGlyphVector extends GlyphVector
     for(int i = 0; i < nGlyphs; i++)
       {
        codePoints[i] = s.codePointAt( stringIndex );
-       // UTF32 surrogate handling
+        // UTF32 surrogate handling
        if( codePoints[i] != (int)s.charAt( stringIndex ) )
          stringIndex ++;
        stringIndex ++;
+
+        if (Character.isISOControl(codePoints[i]))
+          {
+            // Replace with 'hair space'. Should better be 'zero-width space'
+            // but that doesn't seem to be supported by default font.
+            codePoints[i] = 8202;
+          }
       }
 
    glyphCodes = getGlyphs( codePoints );
@@ -242,22 +252,31 @@ public class FreetypeGlyphVector extends GlyphVector
   public void performDefaultLayout()
   {
     logicalBounds = null; // invalidate caches.
-    glyphPositions = null;
-
-    glyphTransforms = new AffineTransform[ nGlyphs ]; 
-    double x = 0;
+    glyphTransforms = new AffineTransform[nGlyphs];
+    Arrays.fill(glyphTransforms, null);
+    glyphPositions = new float[(nGlyphs + 1) * 2];
 
+    GlyphMetrics gm = null;
+    float x = 0;
+    float y = 0;
     for(int i = 0; i < nGlyphs; i++)
       {
-       GlyphMetrics gm = getGlyphMetrics( i );
-       glyphTransforms[ i ] = AffineTransform.getTranslateInstance(x, 0);
-       x += gm.getAdvanceX();
-       if( i > 0 )
-         {
-           Point2D p = getKerning( glyphCodes[ i - 1 ], glyphCodes[ i ] );
-           x += p.getX();
-         }
+        gm = getGlyphMetrics( i );
+        glyphPositions[i*2] = x;
+        glyphPositions[i*2 + 1] = y;
+
+        x += gm.getAdvanceX();
+        y += gm.getAdvanceY();
+        
+        if (i != nGlyphs-1)
+          {
+            Point2D p = getKerning(glyphCodes[i], glyphCodes[i + 1]);
+            x += p.getX();
+            y += p.getY();
+          }
       }
+    glyphPositions[nGlyphs * 2] = x;
+    glyphPositions[nGlyphs * 2 + 1] = y;
   }
 
   /**
@@ -276,7 +295,7 @@ public class FreetypeGlyphVector extends GlyphVector
   {
     int[] rval;
 
-    if( codeReturn == null )
+    if( codeReturn == null || codeReturn.length < numEntries)
       rval = new int[ numEntries ];
     else
       rval = codeReturn;
@@ -286,9 +305,6 @@ public class FreetypeGlyphVector extends GlyphVector
     return rval;
   }
 
-  /**
-   * FIXME: Implement me.
-   */
   public Shape getGlyphLogicalBounds(int glyphIndex)
   {
     GlyphMetrics gm = getGlyphMetrics( glyphIndex );
@@ -296,10 +312,17 @@ public class FreetypeGlyphVector extends GlyphVector
       return null; 
     Rectangle2D r = gm.getBounds2D();
     Point2D p = getGlyphPosition( glyphIndex );
-    return new Rectangle2D.Double( p.getX() + r.getX() - gm.getLSB(), 
-                                  p.getY() + r.getY(),
-                                  gm.getAdvanceX(), 
-                                  r.getHeight() );
+    
+    double[] bounds = new double[] {p.getX() + r.getX() - gm.getLSB(),
+                                    p.getY() + r.getY(),
+                                    p.getX() + r.getX() - gm.getLSB() + gm.getAdvanceX(),
+                                    p.getY() + r.getY() + r.getHeight()};
+    
+    if (glyphTransforms[glyphIndex] != null)
+      glyphTransforms[glyphIndex].transform(bounds, 0, bounds, 0, 4);
+    
+    return new Rectangle2D.Double(bounds[0], bounds[1], bounds[2] - bounds[0],
+                                  bounds[3] - bounds[1]);
   }
 
   /*
@@ -352,7 +375,9 @@ public class FreetypeGlyphVector extends GlyphVector
   public Shape getGlyphOutline(int glyphIndex)
   {
     GeneralPath gp = getGlyphOutlineNative( glyphCodes[ glyphIndex ] );
-    gp.transform( glyphTransforms[ glyphIndex ] );
+    if (glyphTransforms[glyphIndex] != null)
+      gp.transform( glyphTransforms[glyphIndex]);
+    
     return gp;
   }
 
@@ -361,8 +386,8 @@ public class FreetypeGlyphVector extends GlyphVector
    */
   public Point2D getGlyphPosition(int glyphIndex)
   {
-    return glyphTransforms[ glyphIndex ].transform( new Point2D.Double(0, 0),
-                                                  null );
+    return new Point2D.Float(glyphPositions[glyphIndex*2],
+                             glyphPositions[glyphIndex*2 + 1]);
   }
 
   /**
@@ -371,25 +396,12 @@ public class FreetypeGlyphVector extends GlyphVector
   public float[] getGlyphPositions(int beginGlyphIndex, int numEntries, 
                                   float[] positionReturn)
   {
-    if( glyphPositions != null )
-      return glyphPositions;
-
-    float[] rval;
-
-    if( positionReturn == null )
-      rval = new float[2 * numEntries];
-    else
-      rval = positionReturn;
-
-    for( int i = beginGlyphIndex; i < numEntries; i++ )
-      {
-       Point2D p = getGlyphPosition( i );
-       rval[i * 2] = (float)p.getX();
-       rval[i * 2 + 1] = (float)p.getY();
-      }
-
-    glyphPositions = rval;
-    return rval;
+    if (positionReturn == null || positionReturn.length < (numEntries * 2))
+      positionReturn = new float[numEntries*2];
+    
+    System.arraycopy(glyphPositions, beginGlyphIndex*2, positionReturn, 0,
+                     numEntries*2);
+    return positionReturn;
   }
 
   /**
@@ -397,7 +409,7 @@ public class FreetypeGlyphVector extends GlyphVector
    */
   public AffineTransform getGlyphTransform(int glyphIndex)
   {
-    return new AffineTransform( glyphTransforms[ glyphIndex ] );
+    return glyphTransforms[glyphIndex];
   }
 
   /**
@@ -420,10 +432,12 @@ public class FreetypeGlyphVector extends GlyphVector
       return logicalBounds;
 
     Rectangle2D rect = (Rectangle2D)getGlyphLogicalBounds( 0 );
+    AffineTransform tx = new AffineTransform();
     for( int i = 1; i < nGlyphs; i++ )
       {
-       Rectangle2D r2 = (Rectangle2D)getGlyphLogicalBounds( i );
-       rect = rect.createUnion( r2 );
+        Rectangle2D r2 = (Rectangle2D)getGlyphLogicalBounds( i );
+        
+        rect = rect.createUnion( r2 );
       }
 
     logicalBounds = rect;
@@ -444,8 +458,14 @@ public class FreetypeGlyphVector extends GlyphVector
   public Shape getOutline()
   {
     GeneralPath path = new GeneralPath();
+    AffineTransform tx = new AffineTransform();
     for( int i = 0; i < getNumGlyphs(); i++ )
-      path.append( getGlyphOutline( i ), false );
+      {
+        Shape outline = getGlyphOutline(i);
+        tx.setToTranslation(glyphPositions[i*2], glyphPositions[i*2 +1]);
+        outline = tx.createTransformedShape(outline);
+        path.append(outline, false);
+      }
     return path;
   }
 
@@ -485,11 +505,9 @@ public class FreetypeGlyphVector extends GlyphVector
    */
   public void setGlyphPosition(int glyphIndex, Point2D newPos)
   {
-    // FIXME: Scaling, etc.?
-    glyphTransforms[ glyphIndex ].setToTranslation( newPos.getX(), 
-                                                   newPos.getY() );
+    glyphPositions[glyphIndex*2] = (float)(newPos.getX());
+    glyphPositions[glyphIndex*2 + 1] = (float)(newPos.getY());
     logicalBounds = null;
-    glyphPositions = null;
   }
 
   /**
@@ -497,8 +515,7 @@ public class FreetypeGlyphVector extends GlyphVector
    */
   public void setGlyphTransform(int glyphIndex, AffineTransform newTX)
   {
-    glyphTransforms[ glyphIndex ].setTransform( newTX );
     logicalBounds = null;
-    glyphPositions = null;
+    glyphTransforms[glyphIndex] = newTX;
   }
 }