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;
+}