前些时在cauchy同学的帮助下,解决了长期以来困扰我的字体合并问题。这次把相关的东西记录下来备忘。

问题:将一种字体A(一般是一种英文字体)嵌入到另外一种字体B中(一般是一种中文字体),替换掉B字体中对应的字型。为什么要干这种事情呢?很简单,因为大部分中文字体内置的ASCII字型都太难看或者乏味,而英文字体种类远远多与中文字体,你经常可以看到非常漂亮的英文字体,会希望它可以和你喜欢的宋体、或者圆体、或者黑体显示在一起。TeX提供复杂的功能来实现不同语种文字的字体对应,但是最简单最通用的办法还是自己合成一个字体,同时包含你需要的英文字体A和中文字体B。
p.s. 我合成的字体主要用在WoW以及TeX排版中。

要求:除了保持字体不失真、不丢失字符等基本要求之外,还要做到:
1. 操作方法应该是可以方便的跨平台的,因为我大部分时候用Mac,有时用Windows和Linux;
2. 产生的字体应该具备最大限度的跨平台兼容性,支持Mac、Linux、Windows操作系统,可用于一般应用程序和TeX排版引擎。

这个问题并不容易解决,真是不试不知道,昂贵的工具如FontLab Studio居然有5千字符的限制(唉。。。大概只为拉丁语系服务吧),便宜一点的FontCreator只能手工选择字符复制和粘贴,麻烦不说,而且它生成的TrueType字体缺少某些描述符,不能在Mac下被Font Book正常显示。所以才有了下面这个解决方案,let’s go!

解决方案FontForge
这个开放、强大的工具真是无所不能啊,但是要当心,不要被它那个丑陋、缓慢的GUI前端迷惑了,要想做到合并字体这类的事情,还是它的命令行+Python脚本好用——是的,FontForge支持Python脚本,并且提供了数十个函数来帮助你在脚本中使用它的字体处理功能。
然后按照下面的操作步骤进行:

  1. 安装好FontForge,这个根据你的OS可能需要特定的处理,这里就不细说了:
    $ fontforge -version
    Copyright (c) 2000-2008 by George Williams.
     Executable based on sources from 16:34 GMT 30-Mar-2008.
     Library based on sources from 15:57 GMT 30-Mar-2008.
    fontforge 20080330
    libfontforge 20080330
    
  2. 准备一个临时目录,把你要合并的英文字体A、中文字体B放到目录下;
  3. 准备好下面这个脚本,将其命名为font-merge.pe,保存在上述临时目录下:
    # Pre-operation for some non-standard Chinese font file
    Open("font_b.ttf")
    SelectAll()
    ScaleToEm(1024)
    Generate("temp.ttf", "", 0x14)
    Close()
    
    # Open English font and merge to the Chinese font
    Open("font_a.ttf")
    SelectAll()
    ScaleToEm(1024)
    
    MergeFonts("temp.ttf")
    SetFontNames("FontName", "Font Family", "Full Name", "Style", "")
    Generate("font_merged.ttf", "", 0x14)
    Close()
    

    这里注意几点:

    • 第2行:这里括号里指定中文字体的文件名,和你放到临时目录中的保持一致;
    • 第9行:这里括号里指定英文字体的文件名,和你放到临时目录中的保持一致;
    • 第14行:这里设置输出字体的属性,第一个参数是字体的PostScript名,必须英文,不可以有空格,这也是跨平台唯一的标识;第二个参数是字体的family名,第三个是字体的full名,这两个都可以带空格;第四个参数是样式描述,可以是”Regular”、”Bold”、”Italic”等;
    • 第15行:这里括号里指定输出字体的文件名,和临时目录中已有文件不要重名。

    具体内容参考FontForge的脚本函数说明都很容易理解。

  4. 在上述临时目录下运行下面的命令:
    $ fontforge -script font-merge.pe
  5. 等待命令运行完成,就可以去临时目录取合成好的字体了。这里有时会有一些warning,但是不要紧;某些中文字体会导致出错,比如著名的微软雅黑,由于这个字体内部做了很多hacking所以很多标准工具都处理不了,这类问题暂时没有办法,反正好用的中文字体还有几种,它不行就换别的好了。另外,这里举例用的都是TrueType字体,事实上OpenType也是支持的,其他比较少见的类型,只要FontForge支持就可以用在这里。

That’s it. 希望对于有类似需要的朋友有帮助。