This redoes my previous patch, now the GTK font peers reuse the
existing code in Sacha's font peers to parse the "name" table!

Also, a few bugs in the NameDecoder class were fixed. There's probably a
lot more synergy to be had between these two peers.

2006-05-20  Sven de Marothy  <[EMAIL PROTECTED]>

        * gnu/java/awt/font/opentype/NameDecoder.java
        Made class public.
        (getName): Use getShort instead of getChar(), fix PS name.
        (decodeName): New method.
        * gnu/java/awt/peer/gtk/GdkFontPeer.java
        (getSubFamilyName): Implement.
        (getPostScriptName): Use the NameDecoder class instead.
        (parsePSName): Removed.
        (getName): Added

Index: gnu/java/awt/font/opentype/NameDecoder.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/java/awt/font/opentype/NameDecoder.java,v
retrieving revision 1.1
diff -U3 -r1.1 NameDecoder.java
--- gnu/java/awt/font/opentype/NameDecoder.java	30 Apr 2006 09:45:11 -0000	1.1
+++ gnu/java/awt/font/opentype/NameDecoder.java	21 May 2006 01:05:13 -0000
@@ -48,7 +48,7 @@
  *
  * @author Sascha Brawer ([EMAIL PROTECTED])
  */
-class NameDecoder
+public class NameDecoder
 {
   public static final int NAME_COPYRIGHT = 0;
 
@@ -122,27 +122,38 @@
 
     nameTable.position(0);
     /* We understand only format 0 of the name table. */
-    if (nameTable.getChar() != 0)
+    if (nameTable.getShort() != 0)
       return null;
 
     macLanguage = getMacLanguageCode(locale);
     msLanguage = getMicrosoftLanguageCode(locale);
-    numRecords = nameTable.getChar();
-    offset = nameTable.getChar();
+    numRecords = nameTable.getShort();
+    offset = nameTable.getShort();
 
     for (int i = 0; i < numRecords; i++)
     {
-      namePlatform = nameTable.getChar();
-      nameEncoding = nameTable.getChar();
-      nameLanguage = nameTable.getChar();
-      nameID = nameTable.getChar();
-      nameLen = nameTable.getChar();
-      nameStart = offset + nameTable.getChar();
+      namePlatform = nameTable.getShort();
+      nameEncoding = nameTable.getShort();
+      nameLanguage = nameTable.getShort();
+      nameID = nameTable.getShort();
+      nameLen = nameTable.getShort();
+      nameStart = offset + nameTable.getShort();
 
       
       if (nameID != name)
         continue;
 
+      // Handle PS seperately as it can be only ASCII, although
+      // possibly encoded as UTF-16BE
+      if ( name == NAME_POSTSCRIPT )
+	{
+	  if( nameTable.get(nameStart) == 0 ) // Peek at top byte
+	    result = decodeName("UTF-16BE", nameTable, nameStart, nameLen);
+	  else
+	    result = decodeName("ASCII", nameTable, nameStart, nameLen);
+	  return result;
+	}
+
       match = false;
       switch (namePlatform)
       {
@@ -393,14 +404,19 @@
   private static String decodeName(int platform, int encoding, int language,
                                    ByteBuffer buffer, int offset, int len)
   {
-    byte[] byteBuf;
-    String charsetName;
-    int oldPosition;
-
-    charsetName = getCharsetName(platform, language, encoding);
+    String charsetName = getCharsetName(platform, language, encoding);
     if (charsetName == null)
       return null;
 
+    return decodeName(charsetName, buffer, offset, len);
+  }
+
+  private static String decodeName(String charsetName,
+                                   ByteBuffer buffer, int offset, int len)
+  {
+    byte[] byteBuf;
+    int oldPosition;
+
     byteBuf = new byte[len];
     oldPosition = buffer.position();
     try
Index: gnu/java/awt/peer/gtk/GdkFontPeer.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java,v
retrieving revision 1.10
diff -U3 -r1.10 GdkFontPeer.java
--- gnu/java/awt/peer/gtk/GdkFontPeer.java	20 May 2006 22:39:13 -0000	1.10
+++ gnu/java/awt/peer/gtk/GdkFontPeer.java	21 May 2006 01:05:13 -0000
@@ -40,6 +40,7 @@
 
 import gnu.classpath.Configuration;
 import gnu.java.awt.peer.ClasspathFontPeer;
+import gnu.java.awt.font.opentype.NameDecoder;
 
 import java.awt.Font;
 import java.awt.FontMetrics;
@@ -54,7 +55,6 @@
 import java.util.Map;
 import java.util.ResourceBundle;
 import java.nio.ByteBuffer;
-import java.io.UnsupportedEncodingException;
 
 public class GdkFontPeer extends ClasspathFontPeer
 {
@@ -81,6 +81,8 @@
       }
   }
 
+  private ByteBuffer nameTable = null;
+
   private native void initState ();
   private native void dispose ();
   private native void setFont (String family, int style, int size, boolean useGraphics2D);
@@ -152,10 +154,26 @@
     setFont (this.familyName, this.style, (int)this.size,
              GtkToolkit.useGraphics2D());
   }
-  
+
+  /**
+   * Unneeded, but implemented anyway.
+   */  
   public String getSubFamilyName(Font font, Locale locale)
   {
-    return null;
+    String name;
+    
+    if (locale == null)
+      locale = Locale.getDefault();
+    
+    name = getName(NameDecoder.NAME_SUBFAMILY, locale);
+    if (name == null)
+      {
+	name = getName(NameDecoder.NAME_SUBFAMILY, Locale.ENGLISH);
+	if ("Regular".equals(name))
+	  name = null;
+      }
+
+    return name;
   }
 
   /**
@@ -174,42 +192,37 @@
    */
   public String getPostScriptName(Font font)
   {
-    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;
-      }
+    String name = getName(NameDecoder.NAME_POSTSCRIPT, 
+			  /* any language */ null);
+    if( name == null )
+      return this.familyName;
+
+    return name;
   }
 
-  private String parsePSName(byte[] bits) throws UnsupportedEncodingException
+  /**
+   * Extracts a String from the font&#x2019;s name table.
+   *
+   * @param name the numeric TrueType or OpenType name ID.
+   *
+   * @param locale the locale for which names shall be localized, or
+   * <code>null</code> if the locale does mot matter because the name
+   * is known to be language-independent (for example, because it is
+   * the PostScript name).
+   */
+  private String getName(int name, Locale locale)
   {
-    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");
-	}
+    if (nameTable == null)
+      {
+	byte[] data = getTrueTypeTable((byte)'n', (byte) 'a', 
+				       (byte) 'm', (byte) 'e');
+	if( data == null )
+	  return null;
 
-    return null;
+	nameTable = ByteBuffer.wrap( data );
+      }
+
+    return NameDecoder.getName(nameTable, name, locale);
   }
 
   public boolean canDisplay (Font font, char c)

Reply via email to