使用 luaotfload 添加字母间距

使用 luaotfload 添加字母间距

luaotfload 的 letterspace 功能在数学模式下不起作用。我尝试实现自己的功能,如下所示:

\documentclass{minimal}

\directlua{
do
  local function mathletterspace(tfmdata, value)
    local ls = tonumber (value)
    if not ls then
      luaotfload.log.report ("both", 0, "letterspace",
                 "Invalid argument to letterspace.")
      return
    end
    if tfmdata.parameters.factor then
      ls = ls * tfmdata.parameters.factor
    end

    for idx,chr in next, tfmdata.characters do
      if chr and chr.width then
        chr.width = chr.width + 2*ls
        chr.commands = {
          { 'right', ls },
          { 'char',  idx }
        }
      end
    end
  end
  fonts.constructors.features.otf.register {
    name         = 'mathletterspace',
    description  = 'add math letterspacing',
    default      = 20,
    initializers = {
      base = mathletterspace,
      node = mathletterspace,
      plug = mathletterspace,
    },
  }
end
}

\begin{document}     

\font\f="DejaVuSerif-Italic:mathletterspace=20" at 10pt
\f

\hfill abcdefxyz\hfill\hbox{}

\hfill$\textfont1=\f abcdefxyz$\hfill\hbox{}

\hfill$\textfont1=\f\displaystyle abcdefxyz$\hfill\hbox{}

$$\textfont1=\f abcdefxyz$$

$$\textfont1=\f\textstyle abcdefxyz$$

\end{document}

但由于宽度字段为零,因此这不起作用。有什么想法可以解决这个问题吗?(我对 luaotfload 和 lua 不太熟悉。)

答案1

正如 Marcel 在您的错误报告中所说:您需要操纵器,而不是初始化器。并且该值是第三个参数(我使用了更大的值以使效果更明显):

\documentclass{article}

\directlua{
do
  local function mathletterspace(tfmdata,_, value)
    local ls = tonumber (value)
    if not ls then
      luaotfload.log.report ("both", 0, "letterspace",
                 "Invalid argument to letterspace.")
      return
    end
    if tfmdata.parameters.factor then
      ls = ls * tfmdata.parameters.factor
    end

    for idx,chr in next, tfmdata.characters do
      if chr and chr.width then 
        chr.width = chr.width + 2*ls
        chr.commands = {
          { 'right', ls },
          { 'char',  idx }
        }
      end
    end
  end
  fonts.constructors.features.otf.register {
    name         = 'mathletterspace',
    description  = 'add math letterspacing',
    default      = 20,
    manipulators = {
      base = mathletterspace,
      node = mathletterspace,
      plug = mathletterspace,
    },
  }
end  
}

\begin{document}

\font\f="DejaVuSerif-Italic:mathletterspace=200" at 10pt
\f

\hfill abcdefxyz\hfill\hbox{}

\hfill$\textfont1=\f abcdefxyz$\hfill\hbox{}

\hfill$\textfont1=\f\displaystyle abcdefxyz$\hfill\hbox{}

$$\textfont1=\f abcdefxyz$$

$$\textfont1=\f\textstyle abcdefxyz$$

\end{document}

在此处输入图片描述

答案2

仅供后人参考:以下代码似乎运行良好。

\directlua{
do
  local function sidebearing(tfmdata, _, value)
    local sb = tonumber (value)
    if not sb then
      luaotfload.log.report ("both", 0, "letterspace",
                             "Invalid argument to letterspace (not a number).")
      return
    end
    if sb == 0 then
      return
    end
    sb = sb * tfmdata.parameters.factor

    for idx,chr in next, tfmdata.characters do
      if chr then
        chr.width    = chr.width + 2 * sb
        chr.commands = {
          { 'right', sb  },
          { 'char',  idx }
        }
      end
    end
  end

  fonts.constructors.features.otf.register {
    name         = 'sidebearing',
    description  = 'additional sidebearing',
    default      = 0,
    manipulators = {
      base = sidebearing,
      node = sidebearing,
      plug = sidebearing,
    },
  }
end
}

相关内容