当 \setmathfont 具有选项 Scale=MatchLowercase 时,出现“尺寸太大”错误

当 \setmathfont 具有选项 Scale=MatchLowercase 时,出现“尺寸太大”错误
\documentclass{article}
\usepackage{unicode-math}
\setmainfont{Georgia}
\setmathfont[Scale=MatchLowercase]{Cambria Math}
\begin{document}
n $n \sqrt[n]{n}$
\end{document}

上面的代码在使用 XeTeX 排版时会产生错误,提示“尺寸太大”。删除[Scale=MatchLowercase]可以解决问题,但我需要我正在使用的其他文本和数学字体组合的选项。

这个问题似乎是最近才出现的。我上次排版使用unicode-math和包含的XeTeX 文档\sqrt[n]{n}大约是在一年前,当时还没有出现这个问题。最新版本之一,即unicode-math0.8m还是0.8n?

尽管如此,输出的 PDF 文件还是没问题的。我不确定我是否应该担心,但不得不不断忽略错误是很不方便的。作为一种解决方法,我^{1/n}现在将使用符号。

答案1

更新

unicode-math v0.8o (2019/03/04) 起,此错误已修复,可供正常Scale使用。更新包括Ulrike Fischer 答案的一个变体更重要的是,fam 2 和 3 中字体尺寸的设置比较混乱

ScaleAgain = 1.00001从和ScaleAgain = 0.99999ScaleAgain = 1.0001和的转变ScaleAgain = 0.9999有效地降低集合的上界 见下面的定理 1。集合 现在终止于 左右 k=10000,也就是 左右Scale=0.153。这意味着,只要用户请求的Scale多于 0.153,然后unicode-math才能正确设置字体尺寸。

如果请求的Scale值低于 0.153,则字体尺寸问题仍然存在。但我们认为正常使用永远不会产生Scale=0.153或更低的值,因此我们在大多数情况下是安全的。查看更详细的分析这里这里


旧答案

虽然我同意 Ulrike Fischer 的观点,认为这是一个unicode-mathbug,但恐怕我不得不反对“\__um_fontdimen_to_percent:nN损坏”的说法。事实上,使用\dim_to_decimal_in_sp:n是一个很大的改进,但它不是真正的问题出在哪里。我将首先提出我的解决方案,然后尝试讨论根本原因。

请注意,以下解决方案只是临时的,直到unicode-math下一版本中修复此问题为止。


解决方案

对于相对简单的解决方案,您可以使用新功能ScaleAgain稍微扭曲字体大小(人眼看不到):

\documentclass{article}
\usepackage{unicode-math}% v0.8n, 2019/02/15
\setmainfont{Georgia}
\setmathfont[Scale=MatchLowercase,ScaleAgain=0.99999]{Cambria Math}
\begin{document}
n $n \sqrt[n]{n}$
\end{document}

再次扩展

实际上,您必须尝试ScaleAgain接近 1 的范围才能进行编译。同样,这个问题将在 的下一个版本中得到修复unicode-math


unicode-math 关于v0.8n溢出行为的一个定理

对于那些对奇怪的溢出行为感兴趣的人来说,这里有一个定理,基于 v0.8nScaleAgain中的两个固定因素。unicode-math

首先来可视化一下哪些Scale是安全的,哪些可能导致问题:

靠近Scale=1
比例1
靠近Scale=1.2
规模1.2
靠近Scale=1.5
比例1.5

全部绿色的线段代表安全Scale因素,而红色的线段代表有问题的。

以下是严格的数学描述:
定理

尤其是Scale=1.031369386,,Scale=1.031374755Scale=1.031384644Scale=1.031390014 都导致 ! Dimension too large。 靠近Scale=1.03138
比例1.03138


讨论

Georgia 和 Cambria Math 的 x 高度分别为986/2048956/2048。 并且Scale=MatchLowercase被 正确转换为Scale=1.03138fontspec现在,如果我们应用建议重新定义\__um_fontdimen_to_percent:nN当使用拉丁现代数学时,我们会惊讶地发现:

\documentclass{article}
\usepackage{unicode-math}% v0.8n, 2019/02/15
% https://tex.stackexchange.com/a/475802, by Ulrike Fischer:
\ExplSyntaxOn
\cs_set:Nn \__um_fontdimen_to_percent:nN
  {
    \fp_eval:n { \dim_to_decimal_in_sp:n { \fontdimen #1 #2 } / 100 }
  }
\ExplSyntaxOff

\newcommand*\tempscale{1.03138}% Also fails at 1.02, 1.05, 1.07
\setmathfont[Scale=\tempscale]{latinmodern-math.otf}

\begin{document}
n $n \sqrt[n]{n}$
\end{document}

仍然会产生! Dimension too large.错误。

更奇怪的是,如果我们改用或的比例因子 1.03137, 1.03139那么您的 Georgia + Cambria Math 示例就可以成功编译,我的拉丁现代数学示例也可以成功编译(无论是否重新定义\__um_fontdimen_to_percent:nN)。

问题的根源ScaleAgain在于 的新功能fontspec,该功能旨在解决长期存在的问题(请参阅使用 unicode-math 和缩放功能放置上标缩放选项无法与 LuaLaTeX 完全兼容)。哦,还有 TeX“不擅长数学”的事实。

要正确设置与数学相关的旧字体尺寸,unicode-math必须加载相同的数学字体三次。但是 TeX 不允许以相同大小加载同一种字体两次,因此unicode-math必须在第二次和第三次加载时以略有不同的大小加载字体。这些略有不同的大小是通过复合ScaleAgain上一个比例因子。这是在 中引入的 主要原因fontspec,因此unicode-math可以ScaleAgain=1.00001第二次执行ScaleAgain=0.99999第三次。作为我的评论指出,unicode-math由于 TeX 的二进制算法,有时无法区分这三种尺寸。

你的例子很“不幸” Scale=1.03138,有 ,翻译成Round( 1.03138 * 2^16 ) = 67593。之后ScaleAgain=1.00001,TeX 看到1.03139,翻译成Round( 1.03139 * 2^16 ) = 67593。因此 TeX 认为第二个系列和第一个系列是相同的字体,并继续在 的指令下覆盖 fontdimen's unicode-math。这会导致溢出,因为新的 fontdimen's 不再是小于一的百分比,而是现在可能变得相当大的物理长度。

使用\setmathfont[Scale=MatchLowercase,ScaleAgain=0.99999]{Cambria Math},我们基本上试图防止 TeX 意外加载相同大小的数学字体。

答案2

我认为的定义\__um_fontdimen_to_percent:nN是错误的,应该\dim_to_decimal_in_sp使用\dim_to_decimal:n

\documentclass{article}
\usepackage{unicode-math}
\ExplSyntaxOn
\cs_set:Nn \__um_fontdimen_to_percent:nN
  {
    \fp_eval:n { \dim_to_decimal_in_sp:n {  \fontdimen #1 #2 } / 100 }
  }
\ExplSyntaxOff
\setmainfont{Georgia}
\setmathfont[Scale=MatchLowercase]{Cambria Math}

\begin{document}
n $n \sqrt[n]{n}$
\end{document}

相关内容