Hello all,
This patch implements several missing GdkFontPeer methods, and provides
a native method to give access to TrueType tables straight from the java
side.

This requires the freetype2 libraries, which isn't much of a dependency
problem. But when building I found myself needing to stick a -lfreetype
in there, so I need someone to help config the build scripts for this.

/Sven
Index: gnu/java/awt/peer/gtk/GdkFontPeer.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java,v
retrieving revision 1.9
diff -U3 -r1.9 GdkFontPeer.java
--- gnu/java/awt/peer/gtk/GdkFontPeer.java	19 Mar 2006 23:02:42 -0000	1.9
+++ gnu/java/awt/peer/gtk/GdkFontPeer.java	20 May 2006 12:49:23 -0000
@@ -53,6 +53,8 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.ResourceBundle;
+import java.nio.ByteBuffer;
+import java.io.UnsupportedEncodingException;
 
 public class GdkFontPeer extends ClasspathFontPeer
 {
@@ -156,9 +158,58 @@
     return null;
   }
 
+  /**
+   * Returns the bytes belonging to a TrueType/OpenType table,
+   * Parameters n,a,m,e identify the 4-byte ASCII tag of the table.
+   *
+   * Returns null if the font is not TT, the table is nonexistant, 
+   * or if some other unexpected error occured.
+   *
+   */
+  private native byte[] getTrueTypeTable(byte n, byte a, byte m, byte e);
+
+  /**
+   * Returns the PostScript name of the font, defaults to the familyName if 
+   * a PS name could not be retrieved.
+   */
   public String getPostScriptName(Font font)
   {
-    return this.familyName;
+    byte[] bits = getTrueTypeTable((byte)'n', (byte) 'a', 
+				   (byte) 'm', (byte) 'e');
+    try 
+      {
+	if(bits == null)
+	  return this.familyName;
+	String s = parsePSName(bits);
+	if( s == null )
+	  return this.familyName;
+	return s;
+      } 
+    catch(UnsupportedEncodingException e)
+      {
+	return this.familyName;
+      }
+  }
+
+  private String parsePSName(byte[] bits) throws UnsupportedEncodingException
+  {
+    ByteBuffer buf = ByteBuffer.wrap( bits );
+    int count = buf.getShort(2);
+    int stringOffset = buf.getShort(4);
+
+    for(int i = 0; i < count; i++)
+      if(buf.getShort(12 + 12 * i) == 6)
+	{
+	  int length = buf.getShort(14 + 12 * i);
+	  int offset = buf.getShort(16 + 12 * i);
+	  // Check if it's ASCII or Unicode
+	  if(bits[stringOffset + offset] == 0)
+	    return new String(bits, stringOffset + offset, length, "UTF-16BE");
+	  else
+	    return new String(bits, stringOffset + offset, length, "ASCII");
+	}
+
+    return null;
   }
 
   public boolean canDisplay (Font font, char c)
@@ -265,7 +316,13 @@
 
   public int getNumGlyphs (Font font)
   {
-    throw new UnsupportedOperationException ();
+    byte[] data = getTrueTypeTable((byte)'m', (byte) 'a', 
+				   (byte)'x', (byte) 'p');
+    if( data == null )
+      return -1;
+
+    ByteBuffer buf = ByteBuffer.wrap( data );       
+    return buf.getShort(4);
   }
 
   public Rectangle2D getStringBounds (Font font, CharacterIterator ci, 
Index: include/gnu_java_awt_peer_gtk_GdkFontPeer.h
===================================================================
RCS file: /sources/classpath/classpath/include/gnu_java_awt_peer_gtk_GdkFontPeer.h,v
retrieving revision 1.5
diff -U3 -r1.5 gnu_java_awt_peer_gtk_GdkFontPeer.h
--- include/gnu_java_awt_peer_gtk_GdkFontPeer.h	30 Apr 2006 10:37:36 -0000	1.5
+++ include/gnu_java_awt_peer_gtk_GdkFontPeer.h	20 May 2006 12:49:24 -0000
@@ -17,6 +17,7 @@
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_getFontMetrics (JNIEnv *env, jobject, jdoubleArray);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_getTextMetrics (JNIEnv *env, jobject, jstring, jdoubleArray);
 JNIEXPORT jobject JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_getGlyphVector (JNIEnv *env, jobject, jstring, jobject, jobject);
+JNIEXPORT jbyteArray JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_getTrueTypeTable (JNIEnv *env, jobject, jbyte, jbyte, jbyte, jbyte);
 
 #ifdef __cplusplus
 }
Index: native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c
===================================================================
RCS file: /sources/classpath/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c,v
retrieving revision 1.15
diff -U3 -r1.15 gnu_java_awt_peer_gtk_GdkFontPeer.c
--- native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c	3 Apr 2006 10:00:05 -0000	1.15
+++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c	20 May 2006 12:49:24 -0000
@@ -35,6 +35,13 @@
    obligated to do so.  If you do not wish to do so, delete this
    exception statement from your version. */
 
+#include <pango/pango.h>
+#include <pango/pangoft2.h>
+#include <pango/pangofc-font.h>
+#include <freetype/ftglyph.h>
+#include <freetype/ftoutln.h>
+#include <freetype/fttypes.h>
+#include <freetype/tttables.h>
 #include "gdkfont.h"
 #include "gnu_java_awt_peer_gtk_GdkFontPeer.h"
 
@@ -465,3 +472,64 @@
 }
 
 
+JNIEXPORT jbyteArray JNICALL 
+Java_gnu_java_awt_peer_gtk_GdkFontPeer_getTrueTypeTable 
+  (JNIEnv *env, jobject self, jbyte n, jbyte a, jbyte m, jbyte e)
+{
+  struct peerfont *pfont = NULL;
+  FT_Face face;
+  FT_ULong length = 0;
+  FT_ULong tag;
+  int error;
+  FT_Byte *buffer;
+  jbyteArray result_array;
+  jbyte *rbuf;
+
+  pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, self);
+  if(pfont == NULL)
+    return NULL;
+
+  gdk_threads_enter ();
+  face = pango_fc_font_lock_face ((PangoFcFont *)pfont->font);
+  tag = FT_MAKE_TAG( n, a, m, e );
+
+  /* Get the length of the table requested */
+  error = FT_Load_Sfnt_Table( face, tag, 0, NULL, &length );
+  if ( error ) 
+    {
+      pango_fc_font_unlock_face ((PangoFcFont *)pfont->font);
+      gdk_threads_leave ();
+      return NULL;
+    }
+
+  buffer = (FT_Byte *)g_malloc0( length );
+  if ( buffer == NULL ) 
+    {
+      pango_fc_font_unlock_face ((PangoFcFont *)pfont->font);
+      gdk_threads_leave ();
+      return NULL;
+    }
+  /* get the table data */
+  error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length );
+  if ( error ) 
+    {
+      pango_fc_font_unlock_face ((PangoFcFont *)pfont->font);
+      g_free(buffer);
+      gdk_threads_leave ();
+      return NULL;
+    }
+
+  /* copy to a jbytearray */
+  result_array = (*env)->NewByteArray (env, length);
+
+  rbuf = (*env)->GetByteArrayElements (env, result_array, NULL);
+  memcpy(rbuf, buffer, length);
+  (*env)->ReleaseByteArrayElements (env, result_array, rbuf, 0);
+
+  g_free(buffer);
+  pango_fc_font_unlock_face ((PangoFcFont *)pfont->font);
+  gdk_threads_leave ();
+
+  /* done */
+  return result_array;
+}

Reply via email to