在 Python 绘图库 Matplotlib 中(https://matplotlib.org),可以使用 Matplotlib 自己的文本布局算法(其中包括一个用于解析 TeX 类数学模式语法子集的解析器)或使用 latex 来渲染文本:文本包装在 TeX 源文件中,由 (la)tex 处理,
- 对于栅格后端,一方面我们解析 dvi 文件(使用自定义解析器 matplotlib.dviread)以提取字形的基线(以便多个文本对象可以相对于其基线对齐),另一方面我们使用 dvipng 将 dvi 转换为 png,然后加载 png 图像并将其渲染到 Matplotlib 的画布上;
- 对于矢量后端(pdf/ps/svg),我们解析 dvi 文件以提取字形的基线以及字形和框的列表(例如,分数条在 dvi 文件中表示为矩形框),然后将字形和框渲染到矢量文件,再次考虑基线。
我想添加使用 luatex 而不是 tex 的支持;主要是为了改进字体支持。不幸的是,如其他地方所述[1],luatex 的 dvi 输出似乎无法以与 tex 相同的方式解析(由于对字体的引用不同),并且还会混淆 dvipng。除了尝试修复解析器之外,我想知道是否可以使用 luatex 的回调直接输出字形列表,即 {字体文件路径 + 面索引 + 字形索引 + 字形坐标} 列表和框列表?
(当文件(例如 .ttc 格式)包含多个面时,面索引是字体文件中面的索引,即https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Open_Face。
[1]LuaTeX .dvi 文件中如何引用非 Unicode 字形?;LuaLaTeX/dvipng:由于缺少字体,转换失败
提前致谢。
答案1
获取字体文件名和字形索引相当容易。我不知道您说的“面索引”是什么意思。获取页面上的位置要棘手得多,并且不包含在下面的示例中,因为在mlist_to_hlist
触发回调时,尚不知道字形最终会出现在页面上的哪个位置。
\documentclass{article}
\usepackage{amsmath}
\usepackage{unicode-math}
\directlua{
local glyph_id = node.id("glyph")
recurse_sublists = function(head)
for n in node.traverse(head) do
if n.id == glyph_id then
print("Glyph")
print(" Filename: " .. font.fonts[n.font].filename)
print(" Glyph index: " .. n.char)
end
if n.list then
recurse_sublists(n.list)
end
end
end
local print_slots = function(head, display_type, penalties)
local newhead = node.mlist_to_hlist(head, display_type, penalties)
recurse_sublists(newhead)
return newhead
end
luatexbase.add_to_callback("mlist_to_hlist", print_slots, "print_slots")
}
\begin{document}
\[
\frac{1}{2\pi i} \int\limits_\gamma f\Bigl(x^{\mathbf{N}\in\mathbb{C}^{N\times 10}}\Bigr)
= \sum_{k=1}^m n(\gamma;a_k)\operatorname{Res}(f;a_k)\,.
\]
\end{document}
在日志中我得到
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 984713
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 984714
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 49
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 50
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 120587
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 119894
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 984962
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 120574
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 119891
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 984713
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 119909
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm/lmroman7-bold.otf
Glyph index: 78
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 8712
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 8450
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 119873
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 215
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 49
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 48
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 984714
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 61
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 119898
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 984973
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 119896
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 61
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 49
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 119899
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 40
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 120574
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 59
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 119886
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 119896
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 41
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm/lmroman10-regular.otf
Glyph index: 82
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm/lmroman10-regular.otf
Glyph index: 101
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm/lmroman10-regular.otf
Glyph index: 115
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 40
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 119891
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 59
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 119886
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 119896
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 41
Glyph
Filename: /usr/local/texlive/2018/texmf-dist/fonts/opentype/public/lm-math/latinmodern-math.otf
Glyph index: 46
即使在您发表评论后,我仍然不确定您真正需要哪些信息。这就是为什么我实现了某种 JSON 序列化,它只是将完整的内容写入mlist
文件。
\documentclass{article}
\usepackage{amsmath}
\usepackage{unicode-math}
\directlua{
local glyph_id = node.id("glyph")
f = io.open("\jobname.mlist", "w")
recurse_sublists = function(head, indent)
indent = indent or 0
local s = string.rep(" ", indent)
f:write("{\string\n")
for n in node.traverse(head) do
for _,v in ipairs(node.fields(n.id)) do
f:write(s .. '"' .. v .. '": ')
if type(n[v]) == "number" then
f:write(n[v])
elseif type(n[v]) == "nil" then
f:write('null')
else
f:write('"' .. tostring(n[v]) .. '"')
end
f:write(',\string\n')
end
if n.list then
f:write(s .. '"list": ')
recurse_sublists(n.list, indent + 2)
end
end
f:write(string.rep(" ", indent - 2) .. "},\string\n")
end
local print_slots = function(head, display_type, penalties)
local newhead = node.mlist_to_hlist(head, display_type, penalties)
recurse_sublists(newhead, 2)
return newhead
end
luatexbase.add_to_callback("mlist_to_hlist", print_slots, "print_slots")
}
\AtEndDocument{\directlua{f:close()}}
\begin{document}
\[
\frac{1}{2\pi i} \int\limits_\gamma f\Bigl(x^{\mathbf{N}\in\mathbb{C}^{N\times 10}}\Bigr)
= \sum_{k=1}^m n(\gamma;a_k)\operatorname{Res}(f;a_k)\,.
\]
\end{document}