TeX 原始级别的 Unicode 数学

TeX 原始级别的 Unicode 数学

我正在寻找如何在 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.texcsplain 包中新发布的文件中执行了此操作。它昨天从我的 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.texUnMaFo 并不神秘

我尝试总结宏程序员的基本信息。如果我错了,请纠正我。

  • 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 能够处理此类情况下的光学尺寸。

  • 将所有代码设置\UmathcodesMathClass.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-`zUnicode 表中的代码设置为罗马直立。这很不舒服。此外,我们(TeX 用户)很懒,{\cal A}在准备文档源时,我们会在文本编辑器中书写而不是选择正确的 unicode 书法 A。

  • 要准备这样的数学字母选择器,\cal我们必须知道,所有数学字母在给定代码下都采用一种字体,因此切换 是不好的。我们对罗马拉丁字符、数字和希腊字符\fam=something使用“基本代码集” 。宏会更改适当基本代码集中的字符。因此,用户可以从基本代码集书写,并且在使用时会创建书法 A。`A-`Z, `a-`z`0-`9"391-"3D5\cal\UmathcodesA\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、 ) 。您可以将大多数这些控制序列设置为直接通过 的等效项。\oplusunicode-math-table.tex\Umathcode\Umathcharnumdef<sequence>=\Umathcodenum<code>

  • 类型为 L 的代码(在 中声明)在精心准备的 UnMaFo 中有两种(或更多)尺寸。因此,在 和中将自动MathClass.txt使用不同的尺寸。\textstyledisplaystyle

  • \mathopen在 中声明为和\mathclose的 控制序列unicode-math-table.tex可以定义为宏,其中\Udelimiter仅指向其代码。因此\langle\rangle\lbrace将在 的上下文中工作。有关更多详细信息,请参阅文件中和\left...\right的扫描过程 。MathClass.txtunicode-math-table.texuni-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 TrPDF 运算符实现的“粗体”。

相关内容