(previous)

Kerning 的实现难题

2025-03-14 by David Jones 这是我正在制作的一个字体,希望你喜欢。 字母是以垂直条纹背景的反白形式呈现,类似于 Schaeffer Versalien。这种图形效果的灵感来源于/抄袭自 Schaefer Versalien,但字母形式是从我找到的模版字体 Arugula 修改而来。 请记住,对于这种字体,绘制的部分是黑色部分。

所以,让我们考虑一个像 SALTY 这样的词: 看起来还行?也许你觉得没问题,没什么好评论的。

那么字距调整(kerning)呢?在这个例子中,是 LT 之间的字距调整。在金属活字印刷的黄金时代,唯一的字距调整是 /f 突出其主体边缘的情况。对于这种情况,我们不会进行字距调整,而且我们也接受这种做法(较大的木制活字可能会用锯子或锉刀进行字距调整,但在这个设计中,切割必须精确对齐条纹;这是一件棘手的事情)。

这是这个特定例子在没有字距调整时的样子:

我不打算来回讨论字距调整的优点,我来这里是为了讨论书呆子气的技术细节。

在大多数正常的字体中,字距调整是通过位置规则 (GPOS lookups) 完成的;但在这里行不通,因为如果我们重新定位 T,使其稍微向左移动,我们会得到这样的灾难:

看起来有点像 LT 被剪裁了,但实际上它们是被覆盖了。L 的黑色部分与 T 重叠,反之亦然:T 的黑色部分与 L 重叠。效果就是你所看到的,LT 共享一个空间,黑色条纹重叠并变为实心,从而消除了反白字母形式。

那么,如果不能使用 GSPOS lookups,我该如何调整这个字体的字距呢?

使用 GSUB lookups!GSUB(用于替换)lookups 将一个字形序列替换为另一个字形序列。细节可能非常复杂,但我在这里使用它们的方式相对简单。

我将 LT 分成两部分,并将中间两部分重新组合成字距调整部分。

我将用步骤来说明。使用人为分隔开的字形,以便你可以看到每个单独的字形。

LT 作为单独的字形

LT 各自分成两部分。因此,我们得到 4 个字形:/L.left /L.right /T.left T.right。这是通过类似 sub L by L.left L.right ;GSUB lookup 规则完成的。

中间两部分,/L.rightT.left,被我称之为 joiner 的东西替换,joinerLT 共享的中间字距调整部分。

这里的 GSUB 规则如下所示 sub L.right T.left by L_T.joiner ;

实际上就是这样。下一张图片只是前一张图片去掉了额外的间距,也就是它实际显示的样子。

备注

垂直条纹的图案意味着字距调整只能是条纹重复的倍数(不完全是这样,我已经勾勒出了更通用的版本,但对于这个字体来说确实如此)。

图案中的间隙有助于避免实心的黑对黑连接,当一切都是矢量时,这可能有效,但在栅格化时往往会留下小于 1 像素的间隙。这些间隙也是字形没有被分成两半来制作 .left.right 部分的原因。这将留下小于 1 像素的间隙。最好在间隙处分割。

在上面的规则中使用的字形名称,在这个级别上并不重要,但我怀疑会影响 PDF;特别是从 PDF 复制和粘贴,因此可能需要对名称进行一些调整。

对于参与字距调整的每个字母(字形),它的 .left.right 部分都有两个额外的字形。并且...

对于每个 字距调整对,其连接器都有一个字形,因为每个连接器都是唯一的。这些字形会迅速积累,这表明仅在绝对必要时才进行字距调整。

所有的分割和连接都不是手工绘制的,所有的 GSUB 规则也不是手工制作的。在这两种情况下,这都是 Small Matter of Programming,也称为自定义 Python 脚本。库 fontToolsfontFeatures 在这方面 invaluable

这个字体还没有完成,但现在它是一个真正的字体,并且确实像这样工作。我只调整了 L 的字距,所以还有一些字距需要调整。现在它有一个非常基本的字母表,只有 A 到 Z;我会绘制更多的字母和一些更具装饰性的项目,但我计划让它有一个相当小的 repertoire,部分原因是字距调整和垂直条纹设计增加了约束。

如果你认为字距调整有问题(希望你现在也这么认为),那么考虑一下重音符号和其他变音符号将如何工作。 ;)

END