从Java中的TTF文件加载一些TrueType字体会导致FontFormatException:找不到字体名称

时间:2014-01-21 20:42:01

标签: java fonts awt true-type-fonts

我正在尝试从我的系统上的TTF文件创建一个java.awt.Font实例,但只有一些字体可以加载而不会出错。下面的代码是我在网上找到的一些测试代码。在我的系统上运行时,它能够成功加载285种字体(例如Arial.ttf),但是在83种字体上失败(例如AmericanTypewriter.ttf)。

所有错误都是FontFormatException: Font name not found形式,没有嵌入原因。

java.awt.Font和格式兼容性是否存在已知问题?经过谷歌搜索后我找不到任何东西。

public static void main(String[] args) {
        String rootPath = "/Library/Fonts";

        File root = new File(rootPath);
        if (root.canRead()) {
            String[] fontFiles = root.list();

            Font font = null;
            for (String fontFile : fontFiles) {
                try {
                    System.out.println(fontFile);
                    font = Font.createFont(Font.TRUETYPE_FONT, new File(root + "/" + fontFile));
                    System.out.println(font);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

我的环境是Java 7,OS X Mavericks(10.9.1)。

java version "1.7.0_40"
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) 64-Bit Server VM (build 24.0-b56, mixed mode)

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:4)

好的,经过一番挖掘后发现,这个问题是由于java.awt实现中的一个错误(功能!)造成的。也就是说,如果字体文件的名称表不包含姓氏和全名记录,则加载物理TrueType字体会失败。

为了识别问题,我使用GrepCode从OpenJDK的AWT实现中的相关异常向后追溯。一旦我发现了名称表问题,我使用ttx,一个简洁的TrueType元数据编辑器来添加Java寻找的名称条目。例如:

<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
  American Typewriter
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
  American Typewriter
</namerecord>

现在可以通过Java打开由ttx生成的新TTF文件。耶!

答案 1 :(得分:3)

这是Oracle JDK / OpenJDK功能(bug)。

问题是由sun.font.TrueTypeFont导致的,并且缺少对Mac TrueType字体名称的支持。

TrueTypeFont.java包含用于读取TrueType字体的名称表的检查,仅用于读取Microsoft平台ID名称(platformID == 3),而不是Mac平台ID (platformID == 1)。在许多情况下,OSX上包含的truetype字体只有platformID为1的名称。因此,initNames()方法不会为familyName或{{1}设置值并且fullName之后的代码运行检查以查看它们是否为空(它们当然是空的)并抛出initNames()异常。

在Apple JDK(1.6甚至1.5?)上,Apple并没有使用TrueTypeFont作为FontHandler。他们有自己的实现,称为Font name not found。您甚至无法在Apple JDK上使用sun.font.AppleNativeFont,因为它始终使用sun.font.TrueTypeFont处理程序,该处理程序支持Mac和Microsoft平台ID。

似乎sun.font.AppleNativeFont在OpenJDK或Oracle JDK中不存在,即使Apple&#34;捐赠&#34; Oracle的代码。

从连续性的角度来看,在OpenJDK / Oracle JDK中包含sun.font.AppleNativeFont会很方便。如果sun.font.AppleNativeFont得到改进以包含对Mac TrueType字体的支持,那就更好了。

更新:解决方法。

以下评论中的一个补丁已提交给OpenJDK存储库。如果使用正确的修订版克隆存储库,则可以获取已修补的文件。

TrueTypeFont.java

hg clone -r 8b05f9b91765 http://hg.openjdk.java.net/jdk7/jdk7/jdk复制以下这些文件:

jdk/src/shared/classes/sun/font

到当前JDK(我使用jdk8-b132)的trunk中的同一目录下,编译它,你将获得Mac字体支持。您可能还想应用在Mac字体修补程序之后创建的此修补程序:

http://hg.openjdk.java.net/jdk7/jdk7/jdk/rev/3dabb2f78e73

瞧!