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’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)