do {} while (1);

走自己的路,让他们打的去吧


ConTeXt 中文章节与图表标题的设置

基于 MkIV 混合字体机制的中英文排版预处理方法

Li Yanrui posted @ 3 months ago in TeX 学习琐记 with tags ConTeXt MkIV
TeXworks 安装与试用

最新的 MkIV Beta 版本提供了混合字体机制,虽然目前不是非常完善,譬如还不能与 \ConTeXt typescript 机制配合使用。经过测试,我发现将混合字体机制应用于我写的中西文排版预处理程序,可以比较好的解决中西文字体切换问题,文档编译速度以及内存利用率均比较可观。

MkIV 混合字体机制

MkIV 提供了一个新的宏 \definefontfallback,用于定义一个某个编码区域的字体,可以使用该字体去覆盖其它字体对应编码区域内的字体。MkIV 为 \definefontsynonym 宏添加了一个 fallbacks 参数,该参数值即为 \definefontfallback 所定义的字体名。

下面代码定义了 zhrm 字体:

\definefontfallback[serifwhatever][Serif][0x0020-0x00FF]
\definefontsynonym[zhserif][name:simsun][features=zh]
\definefontsynonym[myserif][zhserif][fallbacks=serifwhatever]
\definefont[zhrm][myserif]

zhrm 字体的 0x0020-0x00FF 区间为 Serif 字体 (ConTeXt 默认英文字体),而其它编码区间为 simsun.ttf 字体。在 MkIV 文档中若使用 zhrm 字体,可直接使用字体切换宏 \zhrm 实现。

注意 \definefontsynonym 宏的 features 参数主要用于设定中文字体的断行规则,参数值 zh 由以下代码定义:

\definefontfeature[zh][mode=node,script=hang,lang=zhs]

同理,下面代码定义了 zhrmbold 字体,即 zhrm 字体的“粗体”:

\definefontfallback[serifboldwhatever][SerifBold][0x0020-0x00FF]
\definefontsynonym[zhserifbold][name:simhei][features=zh]
\definefontsynonym[myserifbold][zhserifbold][fallbacks=serifboldwhatever]
\definefont[zhrmbold][myserifbold]

zhrmbold 字体的 0x0020-0x00FF 区间为 SerifBold 字体,其它编码区间则为 simhei.ttf 字体。

我们可以利用这种字体虚拟机制定义更多的字体,但对我而言,zhrm 与 zhrmbold 字体已经可以满足我大部分需求,它们可分别用作文档正文字体与章节标题字体。如果欲排版程序源码,并且源码中会出现中文,那么还需要再定义一款等宽字体:

\definefontfallback[monowhatever][Mono][0x0020-0x00FF]
\definefontsynonym[zhmono][name:simkai][features=zh]
\definefontsynonym[mymono][zhmono][fallbacks=monowhatever]
\definefont[zhtt][mymono]

虚拟字体测试

下面对 MkIV 文档对虚拟字体进行测试,其中有关中文字体切换使用的是很“暴力”的虚拟字体切换宏,而中文与西文之间的间隔也是硬性置入“\;”宏来实现的。 

\definefontfeature[zh][mode=node,script=hang,lang=zhs]

\definefontfallback[serifwhatever][Serif][0x0020-0x00FF]
\definefontsynonym[zhserif][name:simsun][features=zh]
\definefontsynonym[myserif][zhserif][fallbacks=serifwhatever]
\definefont[zhrm][myserif]

\definefontfallback[serifboldwhatever][SerifBold][0x0020-0x00FF]
\definefontsynonym[zhserifbold][name:simhei][features=zh]
\definefontsynonym[myserifbold][zhserifbold][fallbacks=serifboldwhatever]
\definefont[zhrmbold][myserifbold]

\definefontfallback[monowhatever][Mono][0x0020-0x00FF]
\definefontsynonym[zhmono][name:simkai][features=zh]
\definefontsynonym[mymono][zhmono][fallbacks=monowhatever]
\definefont[zhtt][mymono]

\setupbodyfont[rm, 12pt]

%-------- 版面细节 --------
\setupheads[indentnext=yes]
\setuphead[chapter][style=\bfc]
\setuphead[section][style=\bfa]

\setupinterlinespace[big]
\setupindenting[2em,yes,always]
\setuptyping[style=\zhtt]

\starttext

\zhrm

\chapter{\zhrmbold 测试\;\ConTeXt\ MkIV\;中文虚拟字体}

\section{\zhrmbold 衬线字体}

许久以来,中文用户一直抱怨一个问题,就是貌似由\;dvipdfmx\;产生的文档,在\;Adobe\;公司官方的\;Acrobat Reader\;下,显得发虚,严重地影响阅读,而相同的字体,如果不用\;dvipdfmx,比如使用\;cairo、quartz\;或者 \;word2007\;进行转化,产生的\;pdf\;就没有这个问题。

\section{\zhrmbold 等宽字体}

\starttyping
#include <stdio.h>
int main (int argc, char **argv)
{
        printf("你好,ConTeXt MkIV");
        return 0;
}
\stoptyping

\section{\zhrmbold 数学公式}

数学公式所采用的字体未变,依然是\;MkIV\;默认字体。

$$
\sum_{p\rm\;prime}f(p) = \int_{t>1}f(t)\,d\pi(t)
$$

\stoptext
 

请在终端中使用 context 命令编译该文档:

$ context your-tex-file

经测试证明使用 MkIV 虚拟字体与使用 ConTeXt Typescript 中文字体相比,文档编译速度提高了大约 10 倍,内存占用减小了 3/4。我尝试着排了一本 220 页的小说,第一次编译时间为 21 秒,第二次只需 10 秒,内存最大瞬间占用大约 240 M。

基于 MkIV 虚拟字体预处理方法

MkIV 中西文排版预处理程序 ctxzh 1.0 版本中,我基于 ConTeXt Typescript 字体机制实现中文字体切换,当段落文本中存在较多的中西文混杂情况时,由于字体切换过于频繁,严重影响文档编译速度。现在基于虚拟字体机制,可以很好地解决这一问题,基本上只需在文档开始处设定正文字体切换,整篇文档的字体也就被决定下来,只有章节标题、程序代码所用字体需要局部进行字体切换。

基于虚拟字体的预处理程序所要完成的工作实际正是前一小节所给出的文档示例所解决的,只是前者是由程序来完成,而后者是由人工硬编码实现。现在,程序已基本写完,正在试用中。

全局相关文章
相关文章

Comments Feed

Head_small

还是期待对中文的完整支持。


Head_small
SDE

尝试了反方向 fallback, 代码如下:

 

\definefontfeature[zh][mode=node,script=hang,lang=zhs]

\definefontsynonym[songti][name:AdobeSongStd-Light][features=zh]
\definefontsynonym[heiti][name:AdobeHeitiStd-Regular][features=zh]
\definefontsynonym[kaiti][name:AdobeKaitiStd-Regular][features=zh]

\definefontfallback[serifwhatever][songti][0x3400-0xFFFD]
\definefontfallback[serifboldwhatever][heiti][0x3400-0xFFFD]
\definefontfallback[serifmonowhatever][kaiti][0x3400-0xFFFD]

\definefontsynonym[myserif][Serif][fallbacks=serifwhatever]
\definefontsynonym[myserifbold][SerifBold][fallbacks=serifboldwhatever]
\definefontsynonym[myserifmono][SerifItalic][fallbacks=serifmonowhatever]

\definetypeface[song][rm][serif][myserif]
\setupbodyfont[song,12pt,rm]
\setupheads[indentnext=yes]
\setuphead[chapter][style=\bfc]
\setuphead[section][style=\bfa]

这样,对章节标题不再需要切换字体。不过有一个很奇怪的问题,\bfa, \itx 等可以给出正确的字体,但 \bf, \it 不能。不知道什么原因造成的。


Head_small
Li Yanrui

:( 当时也尝试过利用 typeface 机制,不过失败了。刚才试了你的例子,发现又可以了。

高兴 ing,再去改预处理程序。


Head_small
Li Yanrui

测试了一下,这样利用反向 fallback 倒是可以正常使用 typescript 机制了。不过 \bf、\it 失效。很是个问题,有时间再研究。


Head_small
SDE

按理说 \bf 和 \bfa 应该差不多,但一个正常一个出问题,这点比较奇怪。