在 lualatex 中使用 unicode-math 并使用字母和数字的文本字体时修复数学重音符号的位置

在 lualatex 中使用 unicode-math 并使用字母和数字的文本字体时修复数学重音符号的位置

对于文档,我被迫使用没有数学匹配的 otf 字体。出于一致性原因,因此我需要使用我的文本字体来表示运算符和数字。到目前为止,我有:

\setmainfont{Source Serif Pro}
\setsansfont{Source Sans Pro}[Scale=MatchLowercase]
\setmonofont{Source Code Pro}[Scale=MatchLowercase]
\setmathfont{Erewhon Math}[Scale=1.1]
\setmathfont[range=up]{Source Serif Pro}
\setmathfont[range=it]{Source Serif Pro Italic}

还不错(至少对于我需要做的事情来说)。我收到了很多来自 fontspec 的投诉,抱怨字体中缺少数学脚本,字体功能不足(例如 Style=MathScript),但排版似乎还不错。我唯一的问题是数学重音符号放错了位置。

例如,考虑这个 MWE:

\documentclass{article}
\usepackage{unicode-math}
\setmainfont{Source Serif Pro}
\setsansfont{Source Sans Pro}[Scale=MatchLowercase]
\setmonofont{Source Code Pro}[Scale=MatchLowercase]
\setmathfont{Erewhon Math}[Scale=1.1]
\setmathfont[range=up]{Source Serif Pro}
\setmathfont[range=it]{Source Serif Pro Italic}

\begin{document}
$\hat V$
\end{document}

通过 LuaLaTeX 编译时,V 顶部的重音在右侧太多了。

是否有可能以某种方式手动“注入”有关重音定位的信息?如果需要,甚至可以使用 lua 脚本……

答案1

您可以通过添加字体功能和修补字体表来设置自定义 top_accent 值,但默认情况下,这将被忽略,因为您没有加载数学字体。因此,您还必须将字体声明为数学字体。然后,它仍然不起作用,因为 LuaTeX 认为该字体是旧式数学字体,因此不应用基于 OpenType 数学字体的 top_accent 值。因此,您必须模拟 OpenType 数学字体。这要求您设置至少一个数学参数。这有点问题,因为这将覆盖主数学字体中的相应参数,因此您必须稍后重新加载主数学字体以再次修复参数。

一种可能的方法是(内联评论)

\documentclass{article}
\usepackage{unicode-math}

% First some catcode setup, not really important
\begingroup
  \long\def\x#1{\directlua{\unexpanded{#1}}}
  \catcode`\#=12 \catcode`\%=12
  \expandafter\endgroup\x{
  --[[Declare a helper \DeclareTopAccent to invoke the package later]]
  local id = luatexbase.new_luafunction'DeclareTopAccent'
  local mappings = {}
  token.set_lua('DeclareTopAccent', id)
  lua.get_functions_table()[id] = function()
    --[[This is executed when the command is called. We have to parse the input. Take a peek at the usage of \DeclareTopAccent below before trying to read the code, then it should be relativly easy to follow]]
    local t = {}
    repeat
      local cp = assert(token.scan_int(), 'No codepoint found')
      token.scan_keyword'='
      t[cp] = assert(token.scan_int(), 'No offset found')
    until not token.scan_keyword';'
    assert(token.scan_token().cmdname == 'relax', 'Final delimiter missing')
    --[[Save the parsed mapping in a global table and then send the index back to TeX]]
    mappings[#mappings+1] = t
    tex.sprint(string.format("top_accents_id=%i", #mappings))
  end

  --[[Now implement the feature. Nothing particularly interesting here, it's 
    the same as almost any use of otf.register: Take the feature value, do some lookups, apply to characters]]
  fonts.constructors.features.otf.register {
    name = 'top_accents_id',
    description = 'Change selected top_accent values',
    initializers = {
      base = function(tfmdata, value, features)
        local mapping = assert(mappings[value], "I'm going to strike")
        local characters = tfmdata.characters
        for cp, top_accent in next, mapping do
          --[[For some reason some properties have different names here than the native LuaTeX name. E.g. top_accent is just accent]]
          assert(characters[cp], 'Why are you doing this to me?').accent = top_accent
        end
        --[[For top_accent to have any effect, LuaTeX must consider this a modern Math font.
          To fake that, we'll provide a dummy parameter if necessary. MinConnectorOverlap = 0 should be relativly safe.
          Remember to reset your math parameters after loading this font]]
        if not tfmdata.mathparameters or not next(tfmdata.mathparameters) then
          tfmdata.mathparameters = { MinConnectorOverlap = 0 }
        end
      end,
    },
  }
}

\setmainfont{Source Serif Pro}
\setmathfont{Erewhon Math}[Scale=1.1]
% Example of usage: \DeclareTopAccent expects pairs of codepoint and top_accent value,
% separated by ; and terminated with \relax.
% The unit of top_accent is milli-em, so in most cases values around 500 are a good starting point.
\setmathfont[range=it, RawFeature={\DeclareTopAccent `\W=550;`\V=450\relax}]{Source Serif Pro Italic}
% Reset Math parameters messed up by the other fonts
\setmathfont{Erewhon Math}[Scale=1.1, range={}]

\begin{document}
$\hat V$
$\hat W$
\end{document}

在此处输入图片描述

但尽管这是可能的,但要使它们适用于所有字符需要做大量工作,而且您仍然无法获得与适当的数学字体一样好的字体。您真的应该尽快尝试切换到 OpenType 数学字体。

相关内容