在 XeTeX 中,如果当前字体没有可用的字形,则会将一条消息打印到日志文件中。输入
\documentclass{scrartcl}
\begin{document}
α
\end{document}
导致日志中出现以下条目:
Missing character: There is no α in font cmr10!
有没有办法检查给定的输入是否具有渲染所需的所有字形,而不依赖于日志文件?显然,没有刷新日志文件的命令,并且(在我通过管道接入正在运行的 XeLaTeX 进程的情况下)我想在 XeTeX 终止之前知道。
答案1
较长的文章
多年前,当我排版并生成字体预览书时,这项任务对我来说是一个大问题,我需要在实际排版之前了解有关字形的所有信息。我将答案分为三个小部分,每个部分都有可编译的 TeX 文件。
第一部分:
xelatex
及其工具
有一种方法xelatex
,在第 8 页间接提到了参考手册。我们可以使用该\XeTeXcharglyph
命令并检查输出是否为0
(或.notdef
检查字形名称)。一旦任何字形未定义,则将零值分配给字符槽。
完成此步骤后,我们可以使用\ifnum...\else...\fi
语句来决定要排版的内容(如果有的话)。在本例中,我测试了四个字母,? A \ a
其中两个已定义,其余两个未定义。我已经从 Manfred Klein 的收藏中下载并安装了 RodgauApesInitials,http://moorstation.org/typoasis/designers/klein04/deco/rodgau_apes.htm
我们运行xelatex mal-kanji1.tex
并且终端显示:
The glyph slot of 003F(hex) is: 0 (.notdef)
The glyph slot of 0041(hex) is: 3 (A)
The glyph slot of 005C(hex) is: 0 (.notdef)
The glyph slot of 0061(hex) is: 29 (a)
这是代码:
% run: xelatex mal-kanji1.tex
\documentclass[a4paper]{article}
\pagestyle{empty}
\usepackage{xltxtra}
\usepackage{fontspec}
\usepackage{pgffor}
\begin{document}
%\font\malfont=RodGauApes.ttf
\font\klein="RodGauApes Initials"
\font\cmr=cmr10%
\message{^^J}% One \n to the terminal...
% U+0041, A, dec 65
\def\checkme#1{%
\klein\message{The glyph slot of #1(hex) is: \the\XeTeXcharglyph"#1 \space
(\XeTeXglyphname\klein\XeTeXcharglyph"#1)^^J}%
%! Cannot use \XeTeXcharglyph with cmr10; not a native platform font.
\ifnum\XeTeXcharglyph"#1=0%
\cmr Undefined glyph!%
\else
\klein\char"#1%
\fi% End of \ifnum...
}% End of \checkme...
\foreach \malglyph in {003F,0041,005C,0061}% ? A \ a
{\checkme\malglyph\cmr\par%
}% End of \foreach...
\end{document}
当我排版一本汉字预览书时,我需要并且使用了这种策略。我使用了许多不同的字体,我需要确切地知道要排版多少个字形。如果缺少一个或多个字形,则由我决定是否排版该矩形。我应该说,字体缺少一些 CJKV 字符是正常的,因为这样的字符太多了。我附上了书中的一张快照,它是单个日文字符/汉字的预览。
最大的缺点是,我们只能在格式上使用此策略xelatex
,并且只能检查较新的字体(TTF、OTF),它不适用于 PFB。这是工作上的严重限制。让我向您展示其他方法。
第2部分:
testfont.tex
TeX 发行版中的一个工具是testfont.tex
file。如果我们运行,例如:
pdftex testfont.tex
系统询问我们字体的名称,我们使用dmjhira
并按 Enter。使用并按 Enter 时会出现一个选项列表\help
。常见的选项是写入\table\bye
后按 Enter。我们正在获取testfont.pdf
文件,这是它的预览。
问题是我们无法自定义它,如果不安装和设置字体,我们就无法输入 TTF 和 OTF 字体。值得检查另一种方法。
第三部分:测量 TeX 框(平假名和片假名作为测试用例)
TeX 的核心在于测量盒子。这是我们将要使用和测试的方法。我们将测试单个字形,但我们可以轻松测量几乎任何东西。定义新框 ( \newbox
) 后,我们虚拟地填充框 ( \setbox
),然后我们可以测量框的宽度、高度和深度 ( \wd
、\ht
和\dp
)。
在下面的例子中,我们排版了平假名(一种日语音节文字),但我们可能会发现几个缺陷。有一个开头空格,行没有理想地断开,空格正在缩小和拉伸,我们不知道排版了多少字形。但这是进一步探索的起点。
值得一提的是,我们可以运行任何主流latex
引擎,例如fontspec
lualatex
包,我们可以在运行或时测试 TTF、OTF 和一些 dfont 文件中的字形xelatex
。我附上了 TeX 代码和结果预览。
% run: *latex mal-kanji2.tex
\documentclass[a4paper]{article}
\pagestyle{empty}% No page number please...
\parindent=0pt% No indentation please...
\rightskip=6cm% And TeXie, :-), please narrow the text width somehow...
\begin{document}
\font\hira=dmjhira at 2ex% Setting up a new font face (Hiragana)...
\newcount\malcounter% Setting up a new counter...
\malcounter=-1% The initialization of the counter
\loop% The core of this example...
\advance\malcounter by 1% Move on to the next glyph...
{\hira\char\malcounter} % Show me the glyph, add space...
%\discretionary{}{}{}% Allow a page break after the glyph... (the first alternative)
\allowbreak% (the second alternative)
\ifnum\malcounter<255\repeat% Run all 256 characters in the font...
\end{document}
我们仅当字形宽度为非零值时才排版字形。装饰字体中有一些例外,但它被认为是糟糕的字体设计。我们添加了一个计数器(\newcount
)来处理排版字形的数量,我们将空格限制为固定尺寸(\fontdimen
3、4 和 7),我们允许换行,简单地说,我们现在可以完全控制输出。
我附上了带有片假名(日语音节文字)的 PDF 文件的一个例子和预览。
% run: *latex mal-kanji3.tex
\documentclass[a4paper]{article}
\pagestyle{empty}
\parindent=0pt
\begin{document}
\newbox\emptybox
\setbox\emptybox=\hbox{}
\newbox\malbox
\font\kata=dmjkata% A new font face to be used (Katakana)...
\newcount\counter
\counter=-1% The counter of glyphs...
\fontdimen3\font=0pt \fontdimen4\font=0pt \fontdimen7\font=0pt
% Eliminate the stretch in spaces, or, we could use \makebox...
\loop% Process all the glyphs...
\advance\counter by 1% Go to the next glyph...
\setbox\malbox=\hbox{\kata\char\counter}% Measure the glyph...
\ifnum\wd\malbox=\wd\emptybox\relax\else% Is width 0pt? Height is not tested (\ht, \dp)...
\texttt{\ifnum\counter<10 0\fi% Add zero in front of number <10...
\the\counter.\copy\malbox\ }% Show me the glyph...
\discretionary{}{}{}%Allow the line break, or, \allowbreak...
\fi% End of \ifnum condition...
\ifnum\counter<255\repeat% Show me all the glyphs in range 0-255...
\end{document}
结论
这些方法有一些局限性。我们无法测试两个字形是否只是旋转、翻转或缩放,我们也不会列出 0-255 区域之外的字形。如果您需要类似的东西,请使用FontForge,因为它有自己的脚本语言并支持Python 脚本。
如果你想知道这封信下最后一封信的第一个例子中的那个飞溅是什么:哦,是的,那是伟大的 Manfred Klein 传奇字体创造者本人的猿猴!我附上了一张截图FontForge以及包含 26+26 个字母的字体预览。
答案2
作为 Malipivo 出色回答的延伸,我想提一下,您还可以使用\iffontchar
以下示例中所示的方法。请注意,LuaLaTeX 在此处给出的结果与 XeLaTeX 不同 - 看起来 XeLaTeX 不喜欢此处 Unicode 极高范围内的字形(可能高于 U+F0000)。
代码应该相当明显,但这个想法是你调用
\fontrange {xits-math.otf} {1} {"FFFFF} { \texttt{\small #2}:\quad #3\par}
其中第一个参数是 fontspec 字体,第二个参数是起始字形点,第二个参数是终止字形点,第四个参数定义结果如何排版(#2
是字形的十六进制代码,#3
是与字形本身对应的字符)。
\documentclass[a4paper]{article}
\usepackage{fontspec,multicol}
\usepackage[margin=2cm]{geometry}
\begin{document}
\ExplSyntaxOn
\DeclareDocumentCommand \fontrange { m m m +m }
{
\group_begin:
\cs_set:Npn \__typeset:nnn ##1 ##2 ##3 {#4}
\fontspec{#1}
\int_step_inline:nnnn {#2} {1} {#3}
{
\iffontchar\font ##1\relax
\__typeset:nnn {##1} { \int_to_Hex:n {##1} } { \char ##1 \relax }
\fi
}
\group_end:
}
\ExplSyntaxOff
\begin{multicols}{5}
\fontrange{xits-math.otf}{1}{"FFFFF}
{ \texttt{\small U+#2}:\quad #3\par}
% #1 = glyph slot, decimal
% #2 = glyph slot, hex
% #3 = char
\end{multicols}
\end{document}