使用 lualatex,TeXlive 2023。我在 Linux 上,但这个问题肯定适用于任何平台,而不仅仅是 Linux。OpenType 字体,不一定由 TeXlive 提供。
伪代码:
\documentclass{article} % compile with lualatex
\usepackage{fontspec}
\setmainfont{Some Font} % pick anything *otf that might be in TeX or elsewhere.
\typeout{MainFontWithPath=\whateverItIs}
\begin{document}
Hello World
\end{document}
当luaotfload
加载字体时,它当然在加载时就知道该字体的路径。因此,如果用户请求\setmainfont{Some Font}
并且它对应于其/path/to/somefont-regular.otf
系列,则此信息在内部可用。但路径和文件名直到编译的最后阶段才会写入日志文件。
该\listfiles
命令不会列出字体,即使它们已加载。当我在目录中查找时,我没有找到合适listfonts
或等效的字体luaotfload
。
我的问题:如何在字体加载后立即获取列表/path/to/fontfile.otf
,然后解析 AtBeginDocument?如果我有字符串,我知道如何解析。
我无法使用 shell escape 或 aux 文件来执行此操作。
为什么我需要知道:我使用自定义字体,这些字体的度量和字距会不时调整。我可以使用它\directlua
来获取有关实际使用的字体的一些信息,并将该信息存储在 XMP 元数据中。然后,经过一段时间后,如果我发现同一篇文档产生了不同的换行符,我可以查看元数据以查看哪些字体发生了变化(并在必要时恢复旧字体版本)。不幸的是,解析字体文件的代码必须知道文件的路径和文件名 .otf。
密切相关的问题:我知道/path/to/filename.otf
在 Linux 中是如何编写的。在 Windows 或 Mac 中是如何编写的?
答案1
filename
您可以在字体表中访问:
\begin{filecontents*}{fontpath.lua}
local func = luatexbase.new_luafunction'getfontpath'
token.set_lua('getfontpath', func)
local fontid = {token.create'tex_numexpr:D', token.create'tex_fontid:D'}
lua.get_functions_table()[func] = function()
token.put_next(fontid)
local id = token.scan_int()
local fonttable = font.getfont(id)
if not fonttable then
tex.error('No such font', {'Unable to determine filepath for non-existing font'})
end
local path = fonttable.filename
if not path then
local properties = fonttable.properties
path = properties and properties.filename
path = path or kpse.find_file(fonttable.name, 'tfm') or tex.error'Unable to determine font path' or ''
end
tex.sprint(path)
end
\end{filecontents*}
\documentclass{article} % compile with lualatex
\usepackage{fontspec}
\ExplSyntaxOn
\lua_load_module:n{fontpath}
\ExplSyntaxOff
\setmainfont{Liberation Sans}
\typeout{MainFontWithPath=\getfontpath \font \relax}
\begin{document}
Hello World
\end{document}
这里的\getfontpath \font \relax
可以\font
替换为任何 TeX 字体规范。\font
代表当前字体,而例如\textfont 0
将给出文本样式中数学字体系列 0 的路径(但这在序言中不起作用,因为那里数学字体尚未加载)。
答案2
使用 Marcel Krüger 的优秀代码,我提出了一个更简洁的界面来存储和访问字体属性。
\documentclass{article} % Compile with lualatex.
\usepackage{fontspec}
\ExplSyntaxOn
\lua_load_module:n{fontpath} % see https://tex.stackexchange.com/a/709343/4427 for the code
\NewDocumentCommand{\storefontinfo}{mm}
{% #1 = symbolic name, #2 = font declaration
\railg_fontinfo_store:nn { #1 } { #2 }
}
\NewExpandableDocumentCommand{\getfontinfo}{mm}
{% #1 = symbolic name, #2 = property
\prop_item:cn { g_railg_fontinfo_#1_prop } { #2 }
}
\tl_new:N \l__railg_fontinfo_temp_tl
\cs_new_protected:Nn \railg_fontinfo_store:nn
{
\group_begin:
#2
\tl_set:Ne \l__railg_fontinfo_temp_tl { \getfontpath\font }
\prop_new:c { g_railg_fontinfo_#1_prop }
\prop_gput:cne { g_railg_fontinfo_#1_prop } { name } { \fontname\font }
\tl_if_blank:VTF \l__railg_fontinfo_temp_tl
{% no information
\prop_gput:cnn { g_railg_fontinfo_#1_prop } { path } { ?? }
\prop_gput:cnn { g_railg_fontinfo_#1_prop } { size } { 0 }
}
{
\prop_gput:cnV { g_railg_fontinfo_#1_prop } { path } \l__railg_fontinfo_temp_tl
\prop_gput:cne { g_railg_fontinfo_#1_prop } { size }
{ \file_size:V \l__railg_fontinfo_temp_tl }
}
\group_end:
}
\ExplSyntaxOff
\storefontinfo{default}{}
\setmainfont{Libertinus Serif} % Or any font that TeX can find.
\newfontfamily{\test}{Apple Symbols}
\storefontinfo{main}{\normalfont}
\storefontinfo{main-it}{\normalfont\itshape}
\storefontinfo{test}{\test}
\storefontinfo{sf}{\sffamily}
\begin{document}
The filesize of the default font is \getfontinfo{default}{size} bytes.
It was found at \getfontinfo{default}{path}.
The internal name is \getfontinfo{default}{name}.
\bigskip
The filesize of the main font is \getfontinfo{main}{size} bytes.
It was found at \getfontinfo{main}{path}.
The internal name is \getfontinfo{main}{name}.
\bigskip
The filesize of the main italic font is \getfontinfo{main-it}{size} bytes.
It was found at \getfontinfo{main-it}{path}.
The internal name is \getfontinfo{main-it}{name}.
\bigskip
The filesize of the sans font is \getfontinfo{sf}{size} bytes.
It was found at \getfontinfo{sf}{path}.
The internal name is \getfontinfo{sf}{name}.
\bigskip
The filesize of the test font is \getfontinfo{test}{size} bytes.
It was found at \getfontinfo{test}{path}.
The internal name is \getfontinfo{test}{name}.
\end{document}
答案3
对于我使用的 *otf 字体来说,效果非常好。无法研究 Type1,因为我对 TeX 中的 Type1 了解不多。
我没有使用filecontents
上面写的方法,而是将 Lua 代码放入命令中\directlua
,紧接着
\setmainfont
。此外,\typeout
我将字符串保存在一个变量中。然后,其他 Lua 代码获取主字体的文件大小,现在我知道它在哪里了。文件大小被写入CreatorTool
XMP 元数据中无害的字符串中。那些不使用 XMP 的人可能会将文件大小写入其他地方,如果 PDF 的接收者允许的话,甚至可能在 PDF 中可见。为什么是文件大小而不是其他地方?无需解析文件字节即可轻松获取文件大小。此外,我经常在修改字体时忘记更改字体版本号,但它的文件大小不太可能保持不变。也许文件修改日期会很有用,但我不确定所有字体创建者或平台是否都正确记录了它。我不需要记录文件名(我知道,PDF 也知道)或其路径(可以从文件大小确定)。
在下面的例子中,我编辑了 Marcel 的代码,删除了错误消息。如果无法确定请求的信息,则停止编译是没有意义的。
如果您使用此内容,请记得注明出自 Marcel。MWE:
\documentclass{article} % Compile with lualatex.
\usepackage{pdftexcmds} % Gets filesize.
\usepackage{xifthen} % My favorite for tests, in a larger document.
\usepackage{fontspec}
\directlua{
local func = luatexbase.new_luafunction'getfontpath'
token.set_lua('getfontpath', func)
local fontid = {token.create'tex_numexpr:D', token.create'tex_fontid:D'}
lua.get_functions_table()[func] = function()
token.put_next(fontid)
local id = token.scan_int()
local fonttable = font.getfont(id)
if fonttable then
local path = fonttable.filename
end
if not path then
local properties = fonttable.properties
path = properties and properties.filename
path = path or kpse.find_file(fonttable.name, 'tfm') or ''
end
tex.sprint(path)
end
}% End directlua.
\setmainfont{Libertinus Serif} % Or any font that TeX can find.
\edef\MainFontWithPath{\getfontpath \font \relax} % The \font was just set.
\makeatletter
\ifthenelse{\equal{\MainFontWithPath}{}}{
\edef\MainFontFileSize{0} % Could not get the actual value.
}{
\xdef\MainFontFileSize{\pdf@filesize{\MainFontWithPath}}
}
\makeatother
% I write \MainFontFileSize, with other info, into CreatorTool in XMP.
% That is my own code in a custom documentclass, too elaborate for here.
% If you do that, remember that XMP has its own rules for escape characters.
% So, it might be a bad idea to record the path. Numerals are OK.
\begin{document}
Hello. The filesize of the main font is \MainFontFileSize\space bytes.\par
It was found at \MainFontWithPath.
\end{document}