获取字体文件的路径,AtBeginDocument

获取字体文件的路径,AtBeginDocument

使用 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 代码获取主字体的文件大小,现在我知道它在哪里了。文件大小被写入CreatorToolXMP 元数据中无害的字符串中。那些不使用 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}

相关内容