All in all, this makes drawString() about 3 times as fast.

2006-06-11  Sven de Marothy  <[EMAIL PROTECTED]>

        * gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
        (setupGlyphMetrics): New method. Add glyphmetrics caching.
        (getOutline): Operate on the shape directly.
        * gnu/java/awt/peer/gtk/GdkFontPeer.java
        (getGlyphMetrics,putGlyphMetrics): Add GlyphMetrics caching.
        * include/gnu_java_awt_peer_gtk_FreetypeGlyphVector.h
        (getGlyph renamed getGlyphs)
        * java/awt/geom/AffineTransform.java
        (getTranslateInstance): Set fields directly.
        * native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c
        (getGlyphs): Get all glyph codes at once.
        

Index: gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java,v
retrieving revision 1.5
diff -U3 -r1.5 FreetypeGlyphVector.java
--- gnu/java/awt/peer/gtk/FreetypeGlyphVector.java	11 Jun 2006 03:09:03 -0000	1.5
+++ gnu/java/awt/peer/gtk/FreetypeGlyphVector.java	11 Jun 2006 08:23:21 -0000
@@ -84,11 +84,7 @@
    */
   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;
+  private GlyphMetrics[] metricsCache;
 
   /**
    * Create a glyphvector from a given (Freetype) font and a String.
@@ -147,21 +143,25 @@
   {
     nGlyphs = s.codePointCount( 0, s.length() );
     glyphCodes = new int[ nGlyphs ];
+    int[] codePoints = new int[ nGlyphs ];
     int stringIndex = 0;
+
     for(int i = 0; i < nGlyphs; i++)
       {
-	glyphCodes[i] = getGlyph( s.codePointAt(stringIndex) );
+	codePoints[i] = s.codePointAt( stringIndex );
 	// UTF32 surrogate handling
-	if( s.codePointAt( stringIndex ) != (int)s.charAt( stringIndex ) )
+	if( codePoints[i] != (int)s.charAt( stringIndex ) )
 	  stringIndex ++;
 	stringIndex ++;
       }
+
+   glyphCodes = getGlyphs( codePoints );
   }
 
   /**
    * Returns the glyph code within the font for a given character
    */
-  public native int getGlyph(int codepoint);
+  public native int[] getGlyphs(int[] codepoints);
 
   /**
    * Returns the kerning of a glyph pair
@@ -209,14 +209,12 @@
     logicalBounds = null; // invalidate caches.
     glyphPositions = null;
 
-    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);
 	x += gm.getAdvanceX();
 	if( i > 0 )
@@ -266,22 +264,48 @@
 				   gm.getAdvanceX(), r.getHeight() );
   }
 
+  /*
+   * FIXME: Not all glyph types are supported.
+   * (The JDK doesn't really seem to do so either)
+   */
+  public void setupGlyphMetrics()
+  {
+    metricsCache = new GlyphMetrics[ nGlyphs ];
+
+    for(int i = 0; i < nGlyphs; i++)
+      {
+	GlyphMetrics gm = (GlyphMetrics)
+	  peer.getGlyphMetrics( glyphCodes[ i ] );
+	if( gm == null )
+	  {
+	    double[] val = getMetricsNative( glyphCodes[ i ] );
+	    if( val == null )
+	      gm = null;
+	    else
+	      {
+		gm = new GlyphMetrics( true, 
+				       (float)val[1], 
+				       (float)val[2], 
+				       new Rectangle2D.Double
+				       ( val[3], val[4], 
+					 val[5], val[6] ),
+				       GlyphMetrics.STANDARD );
+		peer.putGlyphMetrics( glyphCodes[ i ], gm );
+	      }
+	  }
+	metricsCache[ i ] = gm;
+      }
+  }
+
   /**
    * 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] ),
-			     type );
+    if( metricsCache == null )
+      setupGlyphMetrics();
+
+    return metricsCache[ glyphIndex ];
   }
 
   /**
@@ -406,7 +430,9 @@
   public Shape getOutline(float x, float y)
   {
     AffineTransform tx = AffineTransform.getTranslateInstance( x, y );
-    return tx.createTransformedShape( getOutline() );
+    GeneralPath gp = (GeneralPath)getOutline();
+    gp.transform( tx );
+    return gp;
   }
 
   /**
Index: gnu/java/awt/peer/gtk/GdkFontPeer.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java,v
retrieving revision 1.17
diff -U3 -r1.17 GdkFontPeer.java
--- gnu/java/awt/peer/gtk/GdkFontPeer.java	10 Jun 2006 12:25:17 -0000	1.17
+++ gnu/java/awt/peer/gtk/GdkFontPeer.java	11 Jun 2006 08:23:21 -0000
@@ -57,12 +57,18 @@
 import java.util.Map;
 import java.util.ResourceBundle;
 import java.nio.ByteBuffer;
+import java.util.HashMap;
 
 public class GdkFontPeer extends ClasspathFontPeer
 {
   static native void initStaticState();
   private final int native_state = GtkGenericPeer.getUniqueInteger ();
   private static ResourceBundle bundle;
+
+  /**
+   * Cache GlyphMetrics objects.
+   */
+  private HashMap metricsCache;
   
   static 
   {
@@ -145,6 +151,7 @@
     super(name, style, size);    
     initState ();
     setFont (this.familyName, this.style, (int)this.size);
+    metricsCache = new HashMap();
   }
 
   public GdkFontPeer (String name, Map attributes)
@@ -152,6 +159,7 @@
     super(name, attributes);
     initState ();
     setFont (this.familyName, this.style, (int)this.size);
+    metricsCache = new HashMap();
   }
 
   /**
@@ -375,4 +383,21 @@
     // the metrics cache.
     return Toolkit.getDefaultToolkit().getFontMetrics (font);
   }
+
+  /**
+   * Returns a cached GlyphMetrics object for a given glyphcode,
+   * or null if it doesn't exist in the cache.
+   */
+  GlyphMetrics getGlyphMetrics( int glyphCode )
+  {
+    return (GlyphMetrics)metricsCache.get( new Integer( glyphCode ) );
+  }
+
+  /**
+   * Put a GlyphMetrics object in the cache.
+   */ 
+  void putGlyphMetrics( int glyphCode, Object metrics )
+  {
+    metricsCache.put( new Integer( glyphCode ), metrics );
+  }
 }
Index: include/gnu_java_awt_peer_gtk_FreetypeGlyphVector.h
===================================================================
RCS file: /sources/classpath/classpath/include/gnu_java_awt_peer_gtk_FreetypeGlyphVector.h,v
retrieving revision 1.1
diff -U3 -r1.1 gnu_java_awt_peer_gtk_FreetypeGlyphVector.h
--- include/gnu_java_awt_peer_gtk_FreetypeGlyphVector.h	7 Jun 2006 13:54:32 -0000	1.1
+++ include/gnu_java_awt_peer_gtk_FreetypeGlyphVector.h	11 Jun 2006 08:23:21 -0000
@@ -10,7 +10,7 @@
 {
 #endif
 
-JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyph (JNIEnv *env, jobject, jint);
+JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphs (JNIEnv *env, jobject, jintArray);
 JNIEXPORT jobject JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getKerning (JNIEnv *env, jobject, jint, jint);
 JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getMetricsNative (JNIEnv *env, jobject, jint);
 JNIEXPORT jobject JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphOutlineNative (JNIEnv *env, jobject, jint);
Index: java/awt/geom/AffineTransform.java
===================================================================
RCS file: /sources/classpath/classpath/java/awt/geom/AffineTransform.java,v
retrieving revision 1.9
diff -U3 -r1.9 AffineTransform.java
--- java/awt/geom/AffineTransform.java	2 Jul 2005 20:32:29 -0000	1.9
+++ java/awt/geom/AffineTransform.java	11 Jun 2006 08:23:22 -0000
@@ -414,7 +414,9 @@
   public static AffineTransform getTranslateInstance(double tx, double ty)
   {
     AffineTransform t = new AffineTransform();
-    t.setToTranslation(tx, ty);
+    t.m02 = tx;
+    t.m12 = ty;
+    t.type = (tx == 0 && ty == 0) ? TYPE_UNIFORM_SCALE : TYPE_TRANSLATION;
     return t;
   }
 
Index: native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c
===================================================================
RCS file: /sources/classpath/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c,v
retrieving revision 1.2
diff -U3 -r1.2 gnu_java_awt_peer_gtk_FreetypeGlyphVector.c
--- native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c	7 Jun 2006 23:48:05 -0000	1.2
+++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c	11 Jun 2006 08:23:22 -0000
@@ -81,24 +81,38 @@
   return (PangoFcFont *)pfont->font;
 }
 
-JNIEXPORT jint JNICALL 
-Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyph
-  (JNIEnv *env, jobject obj, jint codepoint)
+JNIEXPORT jintArray JNICALL 
+Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphs
+  (JNIEnv *env, jobject obj, jintArray codepoints)
 {
   FT_Face ft_face;
   jint glyph_index;
+  jintArray retArray;
   PangoFcFont *font;
+  jint *values, *cpvals;
+  jint length;
+  int i;
 
   font = getFont(env, obj);
 
   ft_face = pango_fc_font_lock_face( font );
   g_assert (ft_face != NULL);
 
-  glyph_index = FT_Get_Char_Index( ft_face, codepoint );
+  length = (*env)->GetArrayLength (env, codepoints);
+  cpvals = (*env)->GetIntArrayElements (env, codepoints, NULL);
+
+  retArray = (*env)->NewIntArray (env, length);
+  values = (*env)->GetIntArrayElements (env, retArray, NULL);
+
+  for( i = 0; i < length; i++ )
+    values[i] = FT_Get_Char_Index( ft_face, cpvals[i] );
+
+  (*env)->ReleaseIntArrayElements (env, retArray, values, 0);
+  (*env)->ReleaseIntArrayElements (env, codepoints, cpvals, 0);
 
   pango_fc_font_unlock_face (font);
 
-  return glyph_index;
+  return retArray;
 }
 
 JNIEXPORT jobject JNICALL 
@@ -143,7 +157,7 @@
 
   FT_Set_Transform( ft_face, NULL, NULL );
 
-  if( FT_Load_Glyph( ft_face, glyphIndex, FT_LOAD_DEFAULT ) != 0 )
+  if( FT_Load_Glyph( ft_face, glyphIndex, FT_LOAD_NO_BITMAP ) != 0 )
     {
       pango_fc_font_unlock_face( font );
       printf("Couldn't load glyph %i\n", glyphIndex);

Reply via email to