从 2.7 版开始luaotfload
支持字体功能文件(.fea
)已被删除。
在ConTeXt 邮件列表Hans 演示了如何通过 Lua 进行字体替换。最新的 ConTeXt 发行版中提供了更多示例 (001, 002, 003, 004, 005, 006, 007)
过去我一直使用字体特性文件来实时调整字体的字距。从 Hans 的例子中,我不清楚如何在新语法中调整字距。下面的例子不是按预期工作。
\documentclass{article}
\usepackage{fontspec}
\directlua{
fonts.handlers.otf.addfeature {
name = "kern",
{
type = "pair",
data = {
[0x0041] = { [0x0056] = { false, { -200, 0, 0, 0 } } },
}
}
}
}
\setmainfont{Latin Modern Roman}
\begin{document}
AV
\end{document}
我们能否获得有关如何使用该fonts.handlers
技术调整 LuaTeX 字体功能的全面指南?
相关问题:
(这些涉及到luaotfload.patch_font
回调)
答案1
赤红对于试验新方法很有用,因为它是免费的,并且定义了它可以支持的一些功能。以下是其最新版本中定义的功能:
| r | i | b | bi | sb si |
|------+---+---+---+----+-------|
| c2sc | ✓ | ✓ | ✓ | | |
| kern | ✓ | ✓ | ✓ | ✓ | ✓ |
| liga | | | | ✓ | |
| onum | ✓ | ✓ | | ✓ | |
| ordn | ✓ | | | | |
| pnum | ✓ | ✓ | | ✓ | ✓ |
| smcp | ✓ | ✓ | ✓ | | |
| zero | ✓ | | | | |
连字
最令人惊讶的是,它只liga
以粗体斜体定义,所以让我们先修复它。
以下是我们添加该功能之前的 Crimson:
\documentclass{article}
\usepackage{fontspec}
\setmainfont{Crimson}
\begin{document}
The five baffled officials flew off.
\textit{The five baffled officials flew off.}
\end{document}
现在来修复这个问题:
\documentclass{article}
\usepackage{fontspec}
\directlua{
fonts.handlers.otf.addfeature {
name = "liga",
{
type = "ligature",
data = {
['f_f'] = { "f", "f" },
['f_i'] = { "f", "i" },
['f_f_i'] = { "f", "f", "i" },
['f_l'] = { "f", "l" },
['f_f_l'] = { "f", "f", "l" },
['T_h'] = { "T", "h" },
}
},
"some ligatures"
}
}
\setmainfont{Crimson}
\begin{document}
The five baffled officials flew off.
\textit{The five baffled officials flew off.}
\end{document}
在 中['f_i'] = { "f", "i" }
,['f_i']
是连字的字形名称,{ "f", "i" }
是要连字的字母。因此,如果您的字体将连字称为“fi”而不是“f_i”,则应写入['fi'] = { "f", "i" }
。还请注意,在某些字体中,['f_f_b'] = { "f", "f", "b" }
不起作用,但['f_f_b'] = { "ff", "b" }
可以。
正如 Ulrike Fischer 在tex.stackexchange.com/a/352864在她对这个问题的回答中,如果您luaotfload
最近(2017 年 2 月 4 日)进行了更新,则需要修改\directlua
如下调用:
\directlua{
fonts.handlers.otf.addfeature{
name = "liga",
type = "ligature",
data = {
['f_f'] = { "f", "f" },
['f_i'] = { "f", "i" },
['f_f_i'] = { "f", "f", "i" },
['f_l'] = { "f", "l" },
['f_f_l'] = { "f", "f", "l" },
['T_h'] = { "T", "h" },
},
}
}
风格和语境替代
某些替代字符是否可取取决于附近的情况。例如,Crimson 的长尾“Q”在“u”之前很有吸引力,但如果它出现在单词末尾,则看起来很傻或与其他字形相冲突。比较一下salt
,它在任何地方用替代字符替换字形,以及calt
,它仅在某些情况下替换它:
\documentclass{article}
\usepackage{fontspec}
\directlua{
fonts.handlers.otf.addfeature{
name = "salt",
type = "alternate",
data =
{
Q = "Q.alt01",
},
}
fonts.handlers.otf.addfeature{
name = "calt",
type = "chainsubstitution",
lookups = {
{
type = "substitution",
data = {
["Q"] = "Q.alt01",
},
},
},
data = {
rules = {
{
after = { { "u" } },
current = { { "Q" } },
lookups = { 1 },
},
},
},
}
}
\setmainfont{Crimson}
\begin{document}
(Questions about NASDAQ.) Meh.
{\addfontfeature{RawFeature=+salt}
(Questions about NASDAQ.) Oops!}
{\addfontfeature{RawFeature=+calt}
(Questions about NASDAQ.) That’s better.}
\end{document}
如果 Crimson 的小写字母中有一个长尾 Q,你可以通过添加如下一行来获得它:["q.sc"] = "q.scalt01",
。
上级
在这里我找到了原理,或者说部分原理,但最好不要将其应用于 Crimson,因为上级 4-9 和 0 的设计位置要高于上级 1-3,如下面注释 10 中特别明显:
\documentclass{article}
\usepackage{fontspec,realscripts}
% see Ulrike’s answer at tex.stackexchange.com/a/235302/7883
\renewcommand\footnotemarkfont{\addfontfeature{RawFeature={+sups}}}
\renewcommand\fakesuperscript[1]{#1}
\usepackage[paperwidth=180pt,paperheight=150pt,margin=12pt]{geometry}
\directlua{
fonts.handlers.otf.addfeature {
name = "sups",
{
type = "substitution",
data = {
one = "¹",
["one.onum"] = "¹",
two = "²",
["two.onum"] = "²",
three = "³",
["three.onum"] = "³",
four = "⁴",
["four.onum"] = "⁴",
five = "⁵",
["five.onum"] = "⁵",
six = "⁶",
["six.onum"] = "⁶",
seven = "⁷",
["seven.onum"] = "⁷",
eight = "⁸",
["eight.onum"] = "⁸",
nine = "⁹",
["nine.onum"] = "⁹",
zero = "⁰",
["zero.onum"] = "⁰",
}
},
"footnote figures"
}
}
\setmainfont{Crimson}
\begin{document}
There\footnote{Note.} are\footnote{Note.} far\footnote{Note.}
too\footnote{Note.} many\footnote{Note.} footnotes\footnote{Note.}
in\footnote{Note.} this\footnote{Note.} little\footnote{Note.}
sentence.\footnote{Note.}
\end{document}
如果您想要有脚注数字,则必须添加更多这样的行(例如,["one.prop"] = "¹",
等等),无论您使用的是默认数字、旧式数字、比例数字、斜线零还是提供的任何其他类型的数字。
对于luaotfload
2017 年 2 月,使用\directlua
方式如下:
\directlua{
fonts.handlers.otf.addfeature{
name = "sups",
type = "substitution",
data = {
one = "¹",
["one.onum"] = "¹",
two = "²",
["two.onum"] = "²",
three = "³",
["three.onum"] = "³",
four = "⁴",
["four.onum"] = "⁴",
five = "⁵",
["five.onum"] = "⁵",
six = "⁶",
["six.onum"] = "⁶",
seven = "⁷",
["seven.onum"] = "⁷",
eight = "⁸",
["eight.onum"] = "⁸",
nine = "⁹",
["nine.onum"] = "⁹",
zero = "⁰",
["zero.onum"] = "⁰",
},
}
}
删除连字符
Crimson 对于演示如何移除连字符没有多大用处,因此这里是 FPL Neu(github.com/rstub/fplneu) 不带 'fk' 连字符:
\documentclass{article}
\usepackage{fontspec}
\directlua{
fonts.handlers.otf.addfeature {
name = "nofk",
{
type = "multiple",
data = {
["f_k"] = { "f", "k" },
}
},
"get rid of fk ligatures"
}
}
\setmainfont{FPL Neu}
\begin{document}
Kafka
\addfontfeature{RawFeature=+nofk}
Kafka
\end{document}
在 Garamond Premier Pro 等带有长臂 f 的字体中,结果几乎不可见,而且我似乎无法将此nofk
功能与额外的字距调整结合起来。
对于luaotfload
2017 年 2 月,使用\directlua
方式如下:
\directlua{
fonts.handlers.otf.addfeature{
name = "nofk",
type = "multiple",
data = {
["f_k"] = { "f", "k" },
},
}
}
在标准连字符中选择
有些字体的liga
功能超出了人们的预期。例如,LTC Kaatskill Pro 是一款可爱的 Goudy 设计,它将 œ 变成了标准连字而不是自由连字,结果不仅像“œdema”这样的单词受到影响,甚至“does”和“poem”也受到影响。使用type = "multiple"
,就像上面的“fk”一样,会修复“does”但会干扰“œdema”,所以我们需要另一种方法。
为了说明这一点,我们来看一下免费提供的加洛林小写字母。使用liga
,它产生的结果可以帮助学生轻松进入古文字学课程:
\documentclass[12pt,latin]{octavo}
\usepackage{babel,fontspec,microtype}
\setmainfont{0850 Carolina Tours}
\linespread{1.10345}
\begin{document}
Invocat te, Domine, fides mea quam dedisti mihi, quam inspirasti mihi
per humanitatem Filii tui, per ministerium praedicatoris tui.
\end{document}
出于装饰目的而非学术目的,我们希望删除已定义liga
但当代读者不熟悉的内容。
除了无害的“ff”、“fi”、“fl”、“ft”和“ll”之外,还liga
添加了“oe”连字符和尾目替换“ae”;它还将“i”和“j”替换为无点版本,并将“ſ”替换为“s”,将“u”替换为“v”,将“V”替换为“U”。我们可以通过关闭来删除这些连字和替换liga
,并通过将它们定义为来添加回无害的连字rlig
,这是默认情况下启用的功能:
\documentclass[12pt,latin]{octavo}
\usepackage{babel,fontspec,microtype}
\directlua{
fonts.handlers.otf.addfeature{
name = "rlig",
type = "ligature",
data = {
['f_f'] = { "f", "f" },
['fi'] = { "f", "i" },
['fl'] = { "f", "l" },
['f_t'] = { "f", "t" },
['l_l'] = { "l", "l" },
},
}
}
\setmainfont{0850 Carolina Tours}[
Ligatures=NoCommon]
\linespread{1.10345}
\begin{document}
Invocat te, Domine, fides mea quam dedisti mihi, quam inspirasti mihi
per humanitatem Filii tui, per ministerium praedicatoris tui.
\end{document}
顽固的字体
有时一个或多个连字符不起作用,按上述方法添加它们也无济于事。当字体的查找以错误的顺序定义连字符时,就会发生这种情况,如哈立德·霍斯尼讲话如果查找特别复杂,则在不编辑字体本身的情况下解决问题可能会非常困难,但通常不需要编辑字体。
例如,Goudy 的新风格在其功能中定义了“fi”和“fl” liga
,在其功能中定义了略有不同的“fi”和“fl”字形dlig
。还有“ct”、“fb”、“ff”、“ffi”、“fj”、“ffl”、“fk”、“st”和(斜体)“Th”的字形,但没有定义任何功能来简化它们的使用。添加两个字符的连字可以liga
工作,但添加“ffi”和“ffl”连字则不行,显然是因为“fi”和“fl”连字已经在查找中了。但是如果我们关闭liga
并定义我们想要的连字,那么一切都很好rlig
:
\documentclass{article}
\usepackage{fontspec}
\directlua{
fonts.handlers.otf.addfeature{
name = "rlig",
type = "ligature",
data = {
['ffi'] = { "f", "f", "i" },
['ffl'] = { "f", "f", "l" },
['fb'] = { "f", "b" },
['ff'] = { "f", "f" },
['fh'] = { "f", "h" },
['fi'] = { "f", "i" },
['fj'] = { "f", "j" },
['fk'] = { "f", "k" },
['fl'] = { "f", "l" },
},
}
fonts.handlers.otf.addfeature{
name = "ilig",
type = "ligature",
data = {
['Th'] = { "T", "h" },
['Th.swsh'] = { "T.swsh", "h" },
},
}
}
\setmainfont{Newstyle}[
Script=Default,
Ligatures=NoCommon,
Numbers=OldStyle,
ItalicFeatures={RawFeature=+ilig}]
\begin{document}
The five baffled officials flew off.
\textit{The five baffled officials flew off.}
\textit{\addfontfeatures{Style=Swash}The five baffled officials flew off.}
\end{document}
如果字体的liga
功能包含许多连字符,则更容易继续liga
,只分解有问题的连字符,然后在 中恢复它们rlig
。例如,这会产生与上面相同的输出:
\documentclass{article}
\usepackage{fontspec}
\directlua{
fonts.handlers.otf.addfeature{
name = "nolg",
type = "multiple",
data = {
['fi'] = { "f", "i" },
['fl'] = { "f", "l" },
},
}
fonts.handlers.otf.addfeature{
name = "rlig",
type = "ligature",
data = {
['ffi'] = { "f", "f", "i" },
['ffl'] = { "f", "f", "l" },
['fb'] = { "f", "b" },
['ff'] = { "f", "f" },
['fh'] = { "f", "h" },
['fi'] = { "f", "i" },
['fj'] = { "f", "j" },
['fk'] = { "f", "k" },
['fl'] = { "f", "l" },
},
}
fonts.handlers.otf.addfeature{
name = "ilig",
type = "ligature",
data = {
['Th'] = { "T", "h" },
['Th.swsh'] = { "T.swsh", "h" },
},
}
}
\setmainfont{Newstyle}[
Script=Default,
Numbers=OldStyle,
ItalicFeatures={RawFeature=+ilig},
RawFeature=+nolg]
\begin{document}
The five baffled officials flew off.
\textit{The five baffled officials flew off.}
\textit{\addfontfeatures{Style=Swash}The five baffled officials flew off.}
\end{document}
警告
我真的不明白我做了什么,也许有更好的方法(我很乐意了解),但至少事情或多或少是有效的。
附录
怀着忐忑不安的心情,我创作了我的第一个(也可能是最后一个)GitHub 存储库,我会逐步记录我尝试修复的字体。这应该可以防止这个答案被很少有人接触过的字体讨论所淹没,避免其他使用相同字体的人重复我的劳动,也许还可以让我们共同发现更令人满意的解决方案。
答案2
这个(根据上下文列表中的示例改编)对我有用
2017 年 2 月编辑
语法似乎已经改变。数据和类型不再位于子表中,解释文本会造成伤害。对我来说有效的新代码(在当前的 TeXLive 2016 和 MiKTeX 中)是
\documentclass{article}
\usepackage{fontspec}
\directlua
{
fonts.handlers.otf.addfeature
{
name = "ktest",
type = "kern",
data =
{
["A"] = { ["V"] = -200 },
},
}
}
\setmainfont{Latin Modern Roman}[RawFeature=+ktest]
\setsansfont{Latin Modern Roman}
\begin{document}
AV \sffamily AV
\end{document}
旧版
\documentclass{article}
\usepackage{fontspec}
\directlua{
fonts.handlers.otf.addfeature {
name = "ktest",
{
type = "kern",
data = {
["A"] = { ["V"] = -200 },
}
},
"extra kerns"
}
}
\setmainfont{Latin Modern Roman}[RawFeature=+ktest]
\setsansfont{Latin Modern Roman}
\begin{document}
AV \sffamily AV
\end{document}
但我认为,关于正确的语法(而不是单独使用似乎也可以)和值(-200 是什么单位)还有相当多的未解决的问题["A"]
A
?这些额外的功能应该如何命名?它们都需要一个名字吗?软件包如何实现这些功能并避免与其他软件包发生冲突?