我正在尝试从 LaTeX 生成的 PDF 文件中提取数学内容。大多数提取的符号都能顺利提取。但是有些符号(例如\epsilon
、\Updownarrow
)\simeq
使用非 Unicode 代码,而其他符号(例如)\neq
使用非 Unicode 代码的组合。
\epsilon
SCCPFS+CMMI10
使用嵌入字体和代码 017编写\Updownarrow
使用嵌入的字体KAXSYH+CMSY10
和代码0x6d (m)
\simeq
使用嵌入的字体KAXSYH+CMSY10
和代码0x27 (')
\neq
使用嵌入的字体KAXSYH+CMSY10
和代码0x36 (/)
以及0x3d (=)
在我开始编写一个表格来将字形代码映射到等效的 LaTeX 之前,我想知道是否已经存在这样的反向映射表供 LaTeX 使用。毕竟,原始的 等将在某个地方\epsilon
映射\neq
到一个或多个字形代码。组合情况也需要位置信息,但反向也应该有位置信息。
编辑:我尝试在字体表中查找此信息,但 GSUB 和 GPOS 中没有条目。我应该在那里查找吗?这些信息真的在字体中吗?
编辑:我尝试在文本编辑器中查找 mmap 文件,但它主要是十六进制。有没有可以打开它的工具?
%!PS-Adobe-3.0 Resource-CMap
%%DocumentNeededResources: ProcSet (CIDInit)
%%IncludeResource: ProcSet (CIDInit)
%%BeginResource: CMap (TeXmath-LMR-0)
%%Title: (TeXmath-LMR-0 TeXmath LMR 0)
%%Version: 1.000
%%EndComments
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (TeXmath)
/Ordering (LMR)
/Supplement 0
>> def
/CMapName /TeXmath-LMR-0 def
/CMapVersion 1.000 def
/CMapType 2 def
1 begincodespacerange
<00> <FF>
endcodespacerange
96 beginbfchar
<00> <005C00620069006700630069007200630020>
<01> <005C006D0064006C00670062006C006B0063006900720063006C00650020>
<02> <005C0073007100750061007200650020>
<03> <005C0062006C00610063006B0073007100750061007200650020>
<04> <005C0076006100720074007200690061006E0067006C00650020>
<05> <005C0062006C00610063006B0074007200690061006E0067006C00650020>
<06> <005C0074007200690061006E0067006C00650064006F0077006E0020>
<07> <005C0062006C00610063006B0074007200690061006E0067006C00650064006F0077006E0020>
<08> <005C006C006F007A0065006E006700650020>
<09> <005C0062006C00610063006B006C006F007A0065006E006700650020>
<0A> <005C006D0064006C00670062006C006B006400690061006D006F006E00640020>
编辑:我查找了 \neq 的字符,发现它由两种不同的字体组成,因此这些信息不太可能存在于一种字体中。在 texlive 目录中执行 grep 会给出一些提示:-
% grep -rw neq * | grep -w not
texmf-dist/tex/plain/base/plain.tex:\def\neq{\not=} \let\ne=\neq
texmf-dist/tex/generic/enctex/utf8raw.tex:\mubyte \neq ^^e2^^89^^a0\endmubyte % U+2260 not equal to
texmf-dist/tex/generic/ofs/ofs-cm.tex: \def\neq{\not=}
texmf-dist/tex/latex/listings/lstlang3.sty: myfont,n,nat2string,neq,ngon,norm2,normalmap,not,nu_grid,nubspline,%
texmf-dist/tex/latex/sansmath/sansmath.sty:% two lines, but it did not work well (unbold +, bold greek, bad \neq)
texmf-dist/tex/latex/base/fontmath.ltx:\def\neq{\not=} \let\ne=\neq
texmf-dist/tex/latex/unicode-math/unicode-math-xetex.sty: \cs_gset:cpn { not= } { \neq }
texmf-dist/tex/latex/unicode-math/unicode-math-table.tex:\UnicodeMathSymbol{"02260}{\ne }{\mathrel}{/ne /neq r: not equal}%
texmf-dist/tex/latex/unicode-math/unicode-math-luatex.sty: \cs_gset:cpn { not= } { \neq }
texmf-dist/tex/latex/breqn/cmbase.sym:\DeclareFlexCompoundSymbol{\neq}{Rel}{\not{=}}
texmf-dist/tex/latex/breqn/mathpazo.sym:\DeclareFlexCompoundSymbol{\neq}{Rel}{\not{=}}
texmf-dist/tex/latex/breqn/mathptmx.sym:\DeclareFlexCompoundSymbol{\neq}{Rel}{\not{=}}
答案1
让我们从以下示例开始:
\documentclass{article}
\newcommand*\testsqrtsign[1]{\sqrtsign{\vphantom{#1}}}
\pagestyle{empty}
\begin{document}
\[
\testsqrtsign{|}\testsqrtsign{\big|}\testsqrtsign{\Big|}\testsqrtsign{\bigg|}\testsqrtsign{\Bigg|}
\]
\end{document}
通过 pdfLaTeX 编译上述代码,然后通过 Adobe Acrobat Reader DC 打开 PDF 文件。在打开的 PDF 文件中,按下Ctrl + F
并在查找栏中输入“pqrsvuut”。按下Enter
键或Next
按钮,我们会发现
进一步检查 PDF 文件,我们发现嵌入了一个名为“cmex10”的字体。这个简单的实验可以让您了解数学符号在默认 LaTeX(以及某种程度上 - 原始 TeX)中的编码方式。
回答你的问题
我想知道是否已经存在这样的反向映射表以供在 LaTeX 中使用。
简短的回答是:是的。
第一部分:默认数学编码
根据LaTeX 字体编码指南,默认情况下有 3 种数学字体编码(第 10 页第 2.6 节),即OML
和OMS
。 OMX
具体来说,附录 A.4(第 33-34 页)列出了 3 个表格,显示了每个数学字母/符号的具体编码位置。
例如,
- “希腊数学斜体小写 epsilon” 在
OML
位置'017
(八进制) 或"0F
(十六进制) 处编码,对应字体“cmmi10”(Computer Modern Math Italic 10); - “上下双箭头”在
OMS
位置'155
(八进制)或"6D
(十六进制)处编码,对应字体“cmsy10”(计算机现代数学符号10); - “中的积分符号”在位置(八进制)或(十六进制)
\textstyle
处编码,对应字体“cmex10”(计算机现代数学扩展 10);OMX
'122
"52
第 2 部分:从命令到插槽的映射
\epsilon
包含命令及其对应插槽的映射的代码可以在以下位置\Updownarrow
找到\int
fontdef.dtx
。例如,我们发现这些声明:
...
\DeclareSymbolFont{letters} {OML}{cmm} {m}{it}
\DeclareSymbolFont{symbols} {OMS}{cmsy}{m}{n}
\DeclareSymbolFont{largesymbols}{OMX}{cmex}{m}{n}
...
\DeclareMathSymbol{\epsilon}{\mathord}{letters}{"0F}
...
\DeclareMathDelimiter{\Updownarrow}
{\mathrel}{symbols}{"6D}{largesymbols}{"77}
...
\DeclareMathSymbol{\intop}{\mathop}{largesymbols}{"52}
\def\int{\intop\nolimits}
...
这是您要求的“反向”表:
\epsilon
来自letters
,其OML
编码为 ,位于"0F
。\Updownarrow
,when 不作为分隔符,来自symbols
,其OMS
编码为 ,位于"6D
。\intop
来自largesymbols
,它被OMX
编码并且当用于\textstyle
位于"52
。
第 3 部分:指示 LaTeX 加载实际的字体文件
这部分代码也可以在fontdef.dtx
:
...
\input {omlcmm.fd}
\input {omscmsy.fd}
\input {omxcmex.fd}
...
但似乎与你当前的问题无关。请随意看看(La)TeX 在选择字体时如何使用字体相关文件 [...]?和相关文章以了解更多信息。之所以包含此部分,是因为……
第 4 部分:其他数学字体和非标准编码
这newtxmath
软件包提供了完整的直立希腊字母(\Gammaup
、\alphaup
等)。它们来自,在aslettersA
中声明为newtxmath.sty
...
\DeclareSymbolFont{lettersA}{U}{ntxmia}{m}{it}
...
其中U
代表“未知”。相应的untxmia.fd
文件包含各种字体:“nxlmia”、“zmnmia”、“zcochmia”、“zchmia”、“ntxstx2mia”和“ntxmia”,以及它们的粗体版本。理论上,作者可以对这些字体使用他/她喜欢的任何编码。对于newtxmath
,我们看到
...
\re@DeclareMathSymbol{\Gammaup}{\mathalpha}{lettersA}{0}
...
因此,如果你写下,比如$\bm{\Gammaup}$
,其中\bm
由bm
包,则可以得到一个粗体直立希腊大写字母 Gamma。在 Unicode 中,“Mathematical Bold Capital Gamma” 的编码为U+1D6AA
,而在 的“lettersA”中newtxmath
,它的编码为 0
(十进制,字体中的第一个位置)常规字体和粗体字体。
现在您看到了问题:不能存在将提取的符号转换为其对应的 Unicode 字符的单一映射。
由于数学字体编码缺乏开发(请参阅 LaTeX 字体编码指南,第 1.2 节末尾的最后 3 段),数学字体可以有各种不同的“内部”编码。除了 的newtxmath
“lettersA”(U
-编码)外,还有amsfonts
的“AMSa”和“AMSb”,均为U
-编码;还有mtpro2
的(商业字体)LMP1
和编码;等等LMP2
。LMP3
结束语
市场上除了标准 3 之外还有许多数学字体编码,它们与特定字体绑定。有关输入字符与其对应字体槽之间的映射信息可在支持 LaTeX 包中找到。
由于没有“普遍认可的”数学字体编码,因此不能指望单身的将(如果存在)字形映射回命令/Unicode 字符。
如果你只是想在 PDF 文件中复制粘贴数学公式,那么也许可以unicode-math
尝试一下:
% !TeX program = XeLaTeX or LuaLaTeX
\documentclass{article}
\usepackage{unicode-math}
\begin{document}
\[\int_0^{\pi\pm\epsilon} \sin x \, \symup{d} x = 2 \mp \delta\]
\end{document}
好的——回到默认编码——为什么我们可以在“pqrsvuut”中搜索平方根符号?好吧,前 4 个扩展根符号分别在 、 和 位置编码;而OMX
最后一个“垂直”根符号使用一个、两个和一个拼凑在一起。猜猜在到 位置通常是什么;-)"70
"71
"72
"73
"76
"75
"74
"70
"76
有关 LaTeX 如何处理字体的更多信息,请参阅两个主要参考资料(可在https://ctan.org/pkg/latex-base) 是
- 字体编码指南
- 字体选择指南