我正在寻找如何在 TeX 基元级别(使用 XeTeX 或 LuaTeX 基元)在 XeTeX 或 LuaTeX 中实现 Math OTF 字体的信息。存在一个 LaTeX 包 unicode-math。不幸的是,这个包是面向 LaTeX 的,文档是在 LaTeX 用户级别,并且使用 LaTeX3 语言实现,这与 TeX 基元相去甚远。所以,我不可能从这个包中获得灵感。
在哪里可以找到这样的信息?
我尝试更具体地说明我所寻找的内容。TeX 中的数学排版原则可以总结如下:
您必须使用 \font、\textfont、\scriptfont 和 \scripscriptfont 基元设置(至少)数学系列 2 和 3。此类字体的度量必须包含比基本 7 更多的 \fontdimens(系列 2 的 dim 为 8--22,系列 3 的 dim 为 8--13,它们的使用方式如 TeXbook 附录 G 中所述)。
每个基本数学对象都可以是 \matcode 声明的“字符”或 \mathchardef 声明的“控制序列”。数据指向对象的类型(用于水平间距)和字体的系列加槽。
\delimiter 代码必须指向系列加槽。有指针用于创建连续字符队列(大括号到更大括号)。这些指针以所用字体的字体度量为单位,队列可以以任意大小括号组件的特殊指针结束。部首队列使用类似的原理。
\mathop 类型的对象可以指向两个不同大小的大运算符所在的家族加号槽。它们通过字体度量中的指针连接。
所以,这是(粗略地说)关于 TeX 原始级别的数学排版背景的基本信息。但是当我使用(比如说)texgyrepagella-math.otf 时,这些信息对我来说毫无用处。括号或根号队列的指针在哪里?扩展字体尺寸在哪里?
当然,我知道如何使用 \font primitive 的扩展语法加载此字体,我可以使用 \font primitive 设置字体功能,并且我知道存在原语 \Umathchar 和 \Umathchardef。但这些信息很少。这不足以声明基本的 unicode 数学排版。
有没有像我上面提到的那样,但是针对unicode数学的信息?
答案1
在传统 TeX 中,许多数学模式字体用于根据输入提供输出字形,并且如问题中观察到的\mathcode
输入标记的相关性。相比之下,当使用 Unicode 数学模式字体时只有一种字体用于提供所有字形。因此,Unicode 字体中有大量数学模式特定的条目,而不是 TeX 字体中可用的有限数量的插槽。
两种 Unicode 引擎(XeTeX 和 LuaTeX)都提供了设置实现此功能所需的扩展数学代码的原语\Umathcode
。详细信息可在 XeTeX 和 LuaTeX 手册中找到:语法为
\Umathcode ⟨char slot⟩ [=] ⟨math type⟩ ⟨fam.⟩ ⟨glyph slot⟩
请注意,这里有一个供养家庭的要求,但这些都是相同的。
要设置数学模式工作所需的字体尺寸,引擎或合适的加载器必须读取字体提供的表格。在 XeTeX 中,这是(扩展)\font
原语的一部分,例如
\font\lmmx = "[latinmodern-math.otf]/OT:mode=base;script=math;"
而在 LuaTeX 中,需要基于 Lua 的加载器来扩展\font
原语(开箱即用,与 TeX90 中的相同)(实际上,LuaTeX 使用的字体加载器是luaotfload
,它基于为 ConTeXt 编写的字体加载器,但可以使用纯文本、LaTeX 等加载。目前正在研究将 HarfBuzz 整形器与 LuaTeX 一起使用,但据我所知,目前还无法使用。)
由于只使用一种字体,输入和输出字形之间的转换需要与传统 TeX 有所不同。例如,输入如下
$y = mx + c$
将要不是除非字母具有指向“正确”代码点的正确性,否则将使用斜体字母\Umathcode
。例如,我们需要
\Umathcode `\y = "7 "1 "1D466
(我假设我们将对所有字形使用字体 1:这不是必需的。)
Unicode 数学中的运算符由字体整形器直接缩放,而不需要可扩展部分。因此,\int
为 Unicode 使用定义了类似的东西
\let\int=∫
然后选择正确的数学代码
\Umathcode `∫= "1 "1 `∫
XeTeX 和 LuaTeX 都有\Uradical
部首原语:LuaTeX 也有\Uroot
。
仅使用一种字体的一个重要后果是,例如,使符号加粗需要更改所有相关的数学代码。因此,设置某些东西\bf
需要我们映射所有受影响的代码点并更改它们的\Umathcode
。
虽然只需要一种字体,但必须定义数学系列二和三,以使引擎确信有足够的数学参数可用。(这可能会改变,当然在 LuaTeX 中,因为它似乎是 TeX90 代码路径的保留。)同时,需要加载脚本字体,告诉加载器它们是什么。这导致最小字体加载设置类似于
\font\lmmx = "[latinmodern-math.otf]/OT:mode=base;script=math;" %
\font\lmmvii = "[latinmodern-math.otf]/OT:mode=base;script=math;+ssty=0;" at 7pt %
\font\lmmv = "[latinmodern-math.otf]/OT:mode=base;script=math;+ssty=1;" at 5pt %
\textfont1 = \lmmx
\textfont2 = \lmmx
\textfont3 = \lmmx
\scriptfont1 = \lmmvii
\scriptfont2 = \lmmvii
\scriptfont3 = \lmmvii
\scriptscriptfont1 = \lmmv
\scriptscriptfont2 = \lmmv
\scriptscriptfont3 = \lmmv
(再次,我在这里假设使用 XeTeX 字体语法。)
如评论中所述,Unicode 数学字体中有大量额外的字体尺寸。LuaTeX 给出了这些名称(所有名称均列在 LuaTeX 手册中),而对于 XeTeX,它们具有数字,可使用 进行访问\fontdimen
。
TeX90 基元\delimiter
、\mathaccent
和 \radical
均具有扩展的 Unicode 版本:\Udelimiter
、\Umathaccent
和 \Uradical
。与 TeX90 版本不同,\Udelimiter
和\Uradical
不需要指向多个字形槽:只需要一个槽,字体塑造器负责根据需要增大字形。 的语法与\Umathaccent
相比得到了显著扩展\mathaccent
,对于 LuaTeX 来说更是如此。LuaTeX 手册中描述了这三个基元,XeTeX 手册中对此进行了较少的介绍。
答案2
接受答案中的关键信息是:将 Unicode 数学字体(UnMaFo)加载为系列 2,并将相同的字体作为系列 3。当设置这些系列时,TeX 引擎(XeTeX 或 LuaTeX)会从 UnMaFo 中重新计算系列 2 和系列 3 的适当字体尺寸。
理解了这一点之后,我就可以编写简单的纯 TeX 宏来进行 unicode 数学运算了。我在uni-math.tex
csplain 包中新发布的文件中执行了此操作。它昨天从我的 www 页面镜像到 CTAN,今天又镜像到 TL-pretest。使用uni-math.tex
简单的纯 TeX 宏(包括加载任意大小的字体;例如,此功能用于 OPmac 宏)。您可以将 的 270 行清晰的纯 TeX 代码与uni-math.tex
中的 5671 行进行比较unicode-math.sty
。或者比较使用 跟踪简单的 LaTeX 文档(带有 fontspec 和 unicode-math)时日志文件的千万行与\tracingall
使用 执行相同操作时日志中的 262k 行uni-math.tex
。UnMaFo 并不神秘。
我尝试总结宏程序员的基本信息。如果我错了,请纠正我。
XeTeX 和 LuaTeX 之间没有区别。如果使用 LuaTeX,则只需执行重新声明 \font 原语
\input luafonts
的操作\directlua
。现在,LuaTeX 中的 \font 原语的语法比 XeTeX 中的略有扩展,但使用 XeTeX 语法就足够了,并且适用于两个引擎。如上所述,在系列 2 中加载 UnMaFo,在系列 3 中也加载相同的 UnMaFo。您也可以在系列 1 中加载相同的 UnMaFo,并将所有 Umathcodes 设置为默认系列 1。字体特征必须通过 mode=base;script=math; 附加,并且脚本和 scriptcsript 大小的字体可以分别具有更多字体特征 +ssty=0; 和 +ssty=1;。可能,UnMaFo 能够处理此类情况下的光学尺寸。
将所有代码设置
\Umathcodes
为MathClass.txt
,\Umathcode<code> = <type> 1 <code>
其中 是从 TeX 角度来看的数学对象类型(0 是 Ord,1 是 Op,2 是 Bin 等等)。使用以下转换表将 MathClass.txt 中使用的字母转换为 TeX 类型:L=1、B=2、V=2、R=3、N=0、U=0、F=0、O=4、C=5、P=6。A=7。对于类型 O、C 和 F 的代码,设置\Udelcode<code> = 1 <code>
。它们是可扩展的分隔符。如果正确准备了 UnMaFo,这些代码必须能够垂直扩展。1
设置中请注意:这是加载 UnMaFo 的系列 1。现在,数学排版已准备就绪。但您必须在 之间使用正确的 unicode 代码
$...$
,没有控制序列。特别是,您必须对数学斜体使用直接代码,因为`A-`Z, `a-`z
Unicode 表中的代码设置为罗马直立。这很不舒服。此外,我们(TeX 用户)很懒,{\cal A}
在准备文档源时,我们会在文本编辑器中书写而不是选择正确的 unicode 书法 A。要准备这样的数学字母选择器,
\cal
我们必须知道,所有数学字母在给定代码下都采用一种字体,因此切换 是不好的。我们对罗马拉丁字符、数字和希腊字符\fam=something
使用“基本代码集” 。宏会更改适当基本代码集中的字符。因此,用户可以从基本代码集书写,并且在使用时会创建书法 A。`A-`Z, `a-`z
`0-`9
"391-"3D5
\cal
\Umathcodes
A
\cal
UnMaFo 中有以下数学字母:拉丁罗马字母和希腊字母的 rm、bf、it 和 bi;拉丁字母的 sans、bfsans、itsans 和 bisans;希腊字母的 bfsans 和 bisans;拉丁字母的 cal、bfcal frak、bffrak;拉丁字母的 doublestroke;数字的 rm、bf、sans、bfsans、doublestroked;拉丁字母和数字的 typewriter,参见http://www.unicode.org/charts/PDF/U1D400.pdf。在编写
\cal
类似 的宏时,您必须使用循环从整个基集设置新代码\Umathcode <base-code> = 7 1 <new-code>
。但是 Unicode 表中的数学字母表存在荒谬的漏洞,这是一个小问题(请参阅上面的文档)。因此,必须进行一些宏编程。例如,您可以\umathcharholes
在 中 看到 中的宏uni-math.tex
。如果你已经准备好
\itlatin
了\itgreekrmGreek
类似\cal
上述的宏,那么你可以将其设置\itlatin \itgreekrmGreek
为默认。这是 TeX 中的正常行为。可以从文件中扫描TeX 数学模式中使用的典型控制序列(如
\sum
、\pm
、 ) 。您可以将大多数这些控制序列设置为直接通过 的等效项。\oplus
unicode-math-table.tex
\Umathcode
\Umathcharnumdef<sequence>=\Umathcodenum<code>
类型为 L 的代码(在 中声明)在精心准备的 UnMaFo 中有两种(或更多)尺寸。因此,在 和中将自动
MathClass.txt
使用不同的尺寸。\textstyle
displaystyle
\mathopen
在 中声明为和\mathclose
的 控制序列unicode-math-table.tex
可以定义为宏,其中\Udelimiter
仅指向其代码。因此\langle
、\rangle
等\lbrace
将在 的上下文中工作。有关更多详细信息,请参阅文件中和\left...\right
的扫描过程 。MathClass.txt
unicode-math-table.tex
uni-math.tex
在 中声明为 D(变音符号)的代码
MathClass.txt
可用作\Umathaccent
参数。此原语将广泛的数学重音符(如\widetilde
)声明为默认值。UnMaFo 中为此类代码准备了可扩展性功能。不可扩展的重音符必须用关键字“fixed”声明,可扩展的底部放置重音符在 中有“bottom”关键字 。为所有提到类型的\Umathaccent
序列定义“fixed”数学重音符 。接下来,使用为控制序列 、、、、、 、、、、 、、、 定义更灵活的重音符。unicode-math-table.tex
\mathaccent
\Umathaccent
\overbrace
\underbrace
\overparen
\underparen
\overbracket
\underbracket
\widehat
\widetilde
\overleftharpoon
\overrightharpoon
\overleftarrow
\overrightarrow
\overleftrightarrow
定义
\sqrt
,\cuberoot
并\fourthroot
通过\Uradical
原始指向代码“221A”、“0221B”、“0221C”。准备充分的 UnMaFo 包含这些字符的更多不同大小的变体。(Xe/Lua)TeX 使用适当的大小并添加竖线,就像使用\radical
原始时普通 TeX 所做的那样。声明
\Umathcode `- = 2 1 "2212
因为我们在 TeX 的数学模式中使用连字符作为减号。定义
\let\intop=\int \def\int{\intop \nolimits}
以保留积分运算符的纯 TeX 行为。同样,如果您愿意,也可以对其他类似积分的符号执行此操作。将积分代码声明为 inmath-active,如果您想\int
在文档中使用直接积分符号,请执行类似的技巧。
可以将更多字体加载到下一个系列 4、5、6 等。字体类型无关紧要:UnMaFo 或 Text Unicode 或传统 8bit。然后,如果给定的代码具有类型 7,您可以通过 \fam=number 切换到使用此类字体中的字符。
不幸的是,常见的 UnMaFo 没有完整的粗体数学版本,只有特定的数学字母有 bf 变体,没有其他符号。我们需要在使用粗体文本字体的标题中使用完整的数学粗体。对于这种情况,我使用了2 Tr
PDF 运算符实现的“粗体”。