jjgod / blog Random notes by Jjgod Jiang.

XeTeX 的一个中文处理脚本

其实这个东西早就该写了,只不过我既是一个懒人,也是一个看不惯不完美东西的人,所以一直不好意思去写。

For the impatient: 脚本在这里

XeTeX 是 Johnathan Kew 一开始在 Mac OS X 上开发的一套 TeX 系统的扩展,主要的特点是使用 ATSUI 支持了操作系统 native 的字体,而后使用 ICU 加入了对 complex scripts 等多语言排版的直接支持,算是 TeX 世界中很振奋人心的更新,我也一直在关注着,因为没有 Mac 用,所以不大了解详情。

直到最近 Johnathan 公布了 Linux 系统下的 XeTeX,结合 fontconfig 和 freetype、ICU 一起支持了 Linux 系统下的 native fonts 和多语言排版,并在 Jin Wan Cho (dvipdfmx 的作者之一) 的帮助下扩展了 dvipdfmx,支持 xetex 的“.xdv”输出。所以近期在我的 Arch Linux 上,好好把玩了一阵子 XeTeX (中间的经历,在 newsmthTeX 版和朋友们提过),虽然发现有诸多不便,但仍然觉得这是一个很值得发展的东西。

最大的不便在于 mixed scripts typesetting,即所谓多种语言混杂的排版,因为目前 XeTeX (其实 TeX 也是,只不过无论 CJK 还是 CCT 都用一种比较特别的方法绕过了这个问题,此处按下不表) 无论是哪一段文字,都只有唯一的一种字体,你无法给它指定一个复合字体 (combined font),而复合字体的概念在 DTP 软件中是很常见的 (比如 FrameMaker, InDesign, Scribus 都支持),这就造成了混杂排版的困难:每当语言变化了,就必须手动切换字体,比如用 XeLaTeX,通常使用的是 Will Robertson 写的 fontspec 来选择字体,设置正文的字体用:

\setromanfont[字体特性]{字体名称}

上面这里推荐使用汉字的字体,才能比较好的处理中文的断行 (考虑标点符号的避头尾)。

\XeTeXlinebreaklocale="zh"
\XeTeXlinebreakskip=0pt plus 1pt

然后定义一个英文字体,比如:

\newfontinstance\rmfont{Garamond Premr Pro}
\newcommand{\nc}[1]{{\rmfont #1}}

这样在文档中写的时候是:

中文啦啦啦 \nc{blahblahblah} 中文啦啦啦 \nc{blahblahblah}

一行字还不觉得,英文多了就会很麻烦。目前在 XeTeX 的 mail list 上,已经多次有人 (包括我 ^^|) 提到了这个问题,其实反复思考,这真的不是一个很容易处理的问题,尤其是不仅仅考虑中文和英文两种语言,而是数十种相互字符集范围有交叠的语言时,设计就更费斟酌了,Johnathan 表示他在关注这个问题,但还没有到集中力量解决它的时候,所以我才在这里贴这么一个很 dirty 的 script,其实发现这个问题以后,我反复想了几天,即分析了 XeTeX 的源代码,也去信和 CCT 的作者张林波老师讨论了,最后才决定采用预处理这个方法,觉得这是目前最不伤筋动骨,又能迅速解决问题的方法。

这个脚本就是用来处理中英文混杂的排版,在英文前后自动插入 \nc{} 用于切换字体,你可以在 preamble 定义 \nc 代表的字体。处理时,最 tricky 的部分是中文的标点,其实这一部分在 Unicode 中的代码分布是 Fullwidth Latin Characters 部分,根本不属于汉字部分。

这是用 Python 写的一个很简单的小工具,从 \begin{document} 开始处理,到 \end{document} 结束,目前还不支持任何命令,所以在正文部分如果有 \title{中文标题} 这样的东西,别指望它能正确处理。

此外还有一个功能是在两行连续的中文之间插入 % 以保证源文件中的手动换行不会导致输出结果中出现空白。

这还是一个非常非常 experimental 的东西。欢迎测试,我希望有时间认真写一个 tokenizer 作这个处理,现在的处理是基本上不依赖上下文的,所以能力很弱。另外,还可能在以后加上标点符号的 kerning 处理,类似 CJKpunct 的功能。

当然,我很希望有更多中文的 XeTeX 爱好者和我一同来完成这个工作,:)


7 Comments

听说teTex不再继续开发了,XeTex中文处理能力听你这么一说,似乎还不太成熟吧。teTeX的维护者建议使用TeXlive,不知道老兄有和高见?

Posted by zhllg on 24 May 2006 @ 10am

您可能对 TeX 不大了解。tetex、XeTeX 和 TeXLive 三者,无论在概念和功能上都不是对等的东西。(我在 newsmth 的 TeX 版写过一篇《小谈 TeX 系统的结构与发行版的选择》,可以参考)。

tetex 是一套发行版,TeXLive 也是一套发行版,但其最大的区别不在于核心程序的不同,事实上,发行版只存在维护的问题,而不存在开发的问题,因为所有的程序,包括核心的 tex, etex, pdftex, web2c 到外围的 ps driver, pdf driver 都不是发行版作者开发的,发行版作者只负责编译和打包工作。所以只要核心程序的开发人员仍在开发,那我们的 TeX 就还能用下去。

(XeTeX 正是属于和 tex, etex 对等的核心程序)

前面说了,tetex 和 TeXLive 最大的区别不在程序,那在哪里呢?主要在于对外围宏包、字体、文档等 CTAN 上内容的打包和发布方式的区别。

至于说中文处理能力,现在当然不成熟,但预处理的方法如果仅仅针对中文 (和英文),那还是不难做到完善的,事实上,预处理的方法也是比现在的 CJK 这种 LaTeX 宏包的方式更简洁优雅,也效率更高的方式。

Posted by jjgod on 24 May 2006 @ 3pm

Scribus 中怎样使用复合字体呢,一直没找到。我试着用 fontconfig 来替换某些中文字体的英文部分但是没有效果,应该是思路错了,我 Linux 基础太浅。恳请 Jjgod 指点一下,谢谢。

Posted by Bodhi on 26 November 2009 @ 12pm

再次打扰了…… 还是没有搞定 Scribus 的复合字体,唉……

Posted by Bodhi on 25 December 2009 @ 10pm

@Bodhi: 抱歉,我自己不用 Scribus,所以这个问题帮不上忙了…

Posted by jjgod on 28 December 2009 @ 8pm

@jjgod: 好的,仍然感谢 jjgod。

Posted by Bodhi on 29 December 2009 @ 10pm

[...] TeX Live 2007 已經把 XeTeX 納入,與之搭配的 fontspec套件也是。所以裝完 TeX Live 2007後可以直接使用。原先只適用於 Mac OS X 上的中文 LaTeX方案,現在已經移植到 linux 平台、MS Windows 平台的TeX (拜 TeX Live 2007 之賜)。可以直接使用作業系統裡的任意字型,不需裝設額外的字型描述檔,直接在TeXShop 裡以 unicode寫作多國語言文稿。如果要與他人交流文稿,雙方的字型名稱須一致。底下這個範例,部份參考了 oikos 裡的討論,部份參考了網友 jjgod 關於 XeTeX 的網頁: [...]

Posted by 如何在 Mac OS X 上裝設 LaTeX 以及 CJK 套件 (TeX Live 2007) « ChANG 's Superspace on 3 August 2010 @ 12am

Leave a Comment