2014-01-21 76 views
3

我试图从我的系统上的TTF文件创建一个java.awt.Font实例,但只有一些字体能够加载而没有错误。下面的代码是我在网上找到的一些测试代码。在我的系统上运行时,它能够成功加载285种字体(例如Arial.ttf),但在83种字体(例如AmericanTypewriter.ttf)上失败。从Java中的TTF文件加载一些TrueType字体会导致FontFormatException:找不到字体名称

所有错误的格式为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) 

在这里的任何帮助将不胜感激。

回答

4

好吧,经过一番挖掘,发现这个问题是由于java.awt实现中的一个bug(feature!)造成的。即,如果字体文件的名称表不包含系列名称和全名记录,则加载物理TrueType字体将失败。

为了确定问题,我使用GrepCode从OpenJDK的AWT实现中的相关异常向后追踪。一旦我发现了名称表问题,我使用了一个简单的TrueType元数据编辑器ttx来添加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> 

由ttx生成的新TTF文件现在可以由Java打开。好极了!

+0

我有一个类似的问题,但字体在Java6(Eclipse)中正确加载,但在Java7(终端)中没有。在Java6和7之间的实现似乎有所不同...... – britzl

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()方法不会为familyNamefullName设置值,而initNames()之后的代码将运行检查以查看它们是否为空他们当然是)并抛出了异常。

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

尽管Apple将代码“捐赠”给Oracle,但看起来012xx在OpenJDK或Oracle JDK中不存在。

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

更新:解决方法。

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

hg clone -r 8b05f9b91765 http://hg.openjdk.java.net/jdk7/jdk7/jdk

复制从jdk/src/shared/classes/sun/font这些下列文件:

TrueTypeFont.java 
LCIDMap.java 
AppleLangID.java 

要在当前JDK的躯干在同一目录下(我用jdk8-B132),编译它,你将有Mac的字体支持。您可能还需要应用这个补丁这是在Mac字体补丁后提出:

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

瞧!

+0

有几个人在2011年发布了从未包含的patchback。 http://mail.openjdk.java.net/pipermail/2d-dev/2011-March/001922.html http://mail.openjdk.java.net/pipermail/jdk6-dev/2011-January /002230.html 此处有人要求在2014年再次修复此问题: http://mail.openjdk.java.net/pipermail/awt-dev/2014-January/006860.html –

相关问题