在 pdflatex 中映射私人使用区域字符?

在 pdflatex 中映射私人使用区域字符?

假设我想使用Desconsolata.ttf来自Oracc:开放的丰富注释楔形文字语料库 - Oracc 的 Unicode 字体;特别是,我想使用私人使用区域字符:

fontforge-descon.png

...fontforge显示为 U+E025 和 U+E026。我并不关心这里的正确字体系列等,我只想提取这些字形,而不诉诸fontspec/Lua/XeLatex。

我准备了一个小型的 MWE,其中\write18有一个bash脚本,可以下载并处理字体,以便pdflatex读取它(因此至少需要运行一次pdflatex -shell-escape)。它的编译是成功的(但请注意一个有趣的错误,即“Desconsolata”不能用作字体系列名称,因为它包含“at”作为子字符串),其中打印了和的字体表lmodernDesconsolata单击可查看完整尺寸):

测试-d1.png 测试-d2.png

现在,我知道 Latex 只能支持字体表中最多 255 个字形;并且这些字形显示在排版字体表中。

我也知道,原则上我可以通过在 FontForge 中打开 Desconsolata.ttf 并重新映射私人使用区域字形以使它们最终位于位置 <255 - 然后将其导出为新字体,然后使用它来解决这个问题pdflatex;显然,我不想修改已经存在的字体。

所以我很纳闷 - 有没有办法制作一个映射,这样 Latex 就会在 .ttf 字体的 U+E025 处查找字形编号(例如)63?然后我可以简单地\char在 Latex 文档中的 63 处使用,并加载 .ttf 字体...我想这样的事情可能是可能的,因为我看到了tex/latex/cjk/texinput/UTF8/UTF8.enc类似的东西:

\CJK@namegdef{^^f0}##1##2##3{\@gobble\CJK@unicodexError
                           \CJK@altxchar{-2080}{##1}{##2}{##3}}

...但我就是无法解析这在上下文中的含义。我理解.enc文件是按命令执行的,这些命令要么定义字符,要么不定义字符;例如texmf-dist/fonts/enc/dvips/tex-gyre/q-ts1.enc

...
/dotaccent
/cedilla
/ogonek
/quotesinglbase.ts1
/.notdef
/.notdef
...

...但cjk似乎UTF8.enc直接处理 UTF-8 字节序列。(请注意,我实际上不知道.enc该使用什么,所以我T1-WGL4.enc只是因为我在另一个例子中看到过它的使用)..

以下是代码(注意:mkdir /tmp/mytest; cd /tmp/mytest由于生成的文件数量较多,最好在编译之前做一些类似的操作):

\documentclass{article}

% use pdflatex -shell-escape test.tex to run these commands:
% (tested in `bash` shell, Linux)
% expect:   Warning: ttf2afm (file /tmp/aa/Desconsolata.ttf): glyph `endash' not found ... ;
% note: cannot do bash globbing here, like: echo $(ls *.\string\{afm,map,tfm,fd,log,aux\string\}) ;
%\def\tname{Desconsolata} % NOTE: cannot use Desconsolata as name here, because of f@tstripsize #1at#2pt->#1 -> will cut the name at 'at' in Desconsol'at'a; so: kpathsea: Running mktexmf Desconsol -> ! Font \f@ttestfont=Desconsol at 4.99947pt not loadable: Metric (TFM) file not found. ; so... just call it Desconsol:
\def\tname{Desconsol}
\immediate\write18{%
  rm -v *.afm *.map *.tfm *.fd *.log *.aux ; ls ;
  wget -nc http://oracc.museum.upenn.edu/downloads/Desconsolata-ttf.zip ;
  unzip -n Desconsolata-ttf.zip ;
  ENCFILE="T1-WGL4.enc" ;
  TNAME="\tname" ;
  ttf2afm -e "$ENCFILE" -o $PWD/$TNAME.afm $PWD/Desconsolata.ttf ;
  maplineorig=$(afm2tfm $PWD/$TNAME.afm -T "$ENCFILE") ;
  mapline="$TNAME $TNAME "'" T1Encoding ReEncodeFont " <'"$PWD/Desconsolata.ttf T1-WGL4.enc" ;
  echo $maplineorig ; echo $mapline ;
  echo "$mapline" > $TNAME.map ;
  echo "\string\ProvidesFile{T1$TNAME.fd}[$TNAME Font name/desc/comment]\string" > T1$TNAME.fd ;
  echo >> T1$TNAME.fd ;
  echo "\string\DeclareFontFamily{T1}{$TNAME}{}" >> T1$TNAME.fd ;
  echo "\string\DeclareFontShape{T1}{$TNAME}{m}{n}{ <-> $PWD/$TNAME}{}" >> T1$TNAME.fd ;
  echo >> T1$TNAME.fd ;
  echo '\string\endinput' >> T1$TNAME.fd ;
}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{trace}

\pdfmapfile{=\tname.map}

\usepackage{fonttable}
\makeatletter
\def\myfontinfo{font: encoding \f@encoding, family: \f@family, series: \f@series, shape: \f@shape, size: \f@size, baselineskip: \f@baselineskip}
\makeatother

\begin{document}

  \myfontinfo
  \vspace{-2em}
  %% \xfonttable{ encoding }{ family }{ series }{ shape }
  \makeatletter
    \xfonttable{\f@encoding}{\f@family}{\f@series}{\f@shape}
  \makeatother

  \clearpage

  \footnotesize% just to make small enough to fit on one page
  \fontencoding{T1}\fontfamily{\tname}\selectfont
  \myfontinfo
  \vspace{-2em}
  \makeatletter
    \xfonttable{\f@encoding}{\f@family}{\f@series}{\f@shape}
  \makeatother

\end{document}

答案1

谢谢@UlrikeFischer,现在这个问题已经解决了;答案是:

在 T1-WGL4.enc(本地版本)中,用要测试的字符名称(例如 /cedilla)替换其中一个字符名称(例如 /uniE025),然后查看会发生什么。如果您可以看到字形,则还必须创建合适的 tfm 文件。

这正是嵌入bash代码现在所做的:它复制系统T1-WGL4.enc(使用找到kpsewhich),并使用sed进行就地替换 - 因此,而不是旧的行T1-WGL4.enc

% 0x00
  /grave /acute /circumflex /tilde
  /dieresis /hungarumlaut /ring /caron
  /breve /macron /dotaccent /cedilla
...

...现在本地有新的一行T1-WGL4-D.enc

  /breve /macron /dotaccent /uniE025
...

值得注意的是,这是第 12 个定义,因此它显示为字形 11(= 0x0B 十六进制):

测试-dD.png

... 可以将该图像与 OP 中的表格进行比较,以查看与原始字体编码的区别。此外,如果bash通过 重新运行脚本pdflatex -shell-escape.tfm文件也会被重建,因此使用此代码应该可以立即看到在正常字体之间包含的字形。

\documentclass{article}

% use pdflatex -shell-escape test.tex to run these commands:
% (tested in `bash` shell, Linux)
% expect:   Warning: ttf2afm (file /tmp/aa/Desconsolata.ttf): glyph `endash' not found ... ;
% note: cannot do bash globbing here, like: echo $(ls *.\string\{afm,map,tfm,fd,log,aux\string\}) ;
%\def\tname{Desconsolata} % NOTE: cannot use Desconsolata as name here, because of f@tstripsize #1at#2pt->#1 -> will cut the name at 'at' in Desconsol'at'a; so: kpathsea: Running mktexmf Desconsol -> ! Font \f@ttestfont=Desconsol at 4.99947pt not loadable: Metric (TFM) file not found. ; so... just call it Desconsol:
%   ENCFILE="T1-WGL4.enc" ;
\def\tname{Desconsol}
\immediate\write18{%
  set -x ;
  rm -v *.afm *.map *.tfm *.fd *.log *.aux *.enc ; ls ;
  wget -nc http://oracc.museum.upenn.edu/downloads/Desconsolata-ttf.zip ;
  unzip -n Desconsolata-ttf.zip ;
  ENCFORG="T1-WGL4.enc" ;
  ENCFILE="T1-WGL4-D.enc" ;
  PENCFILE="$PWD/$ENCFILE" ;
  cp $(kpsewhich $ENCFORG) $PENCFILE ;
  sed -i 's_/cedilla_/uniE025_g' $PENCFILE ;
  TNAME="\tname" ;
  ttf2afm -e "$PENCFILE" -o $PWD/$TNAME.afm $PWD/Desconsolata.ttf ;
  maplineorig=$(afm2tfm $PWD/$TNAME.afm -T "$PENCFILE") ;
  mapline="$TNAME $TNAME "'" T1Encoding ReEncodeFont " <'"$PWD/Desconsolata.ttf $PENCFILE" ;
  echo $maplineorig ; echo $mapline ;
  echo "$mapline" > $TNAME.map ;
  echo "\string\ProvidesFile{T1$TNAME.fd}[$TNAME Font name/desc/comment]" > T1$TNAME.fd ;
  echo >> T1$TNAME.fd ;
  echo "\string\DeclareFontFamily{T1}{$TNAME}{}" >> T1$TNAME.fd ;
  echo "\string\DeclareFontShape{T1}{$TNAME}{m}{n}{ <-> $PWD/$TNAME}{}" >> T1$TNAME.fd ;
  echo >> T1$TNAME.fd ;
  echo '\string\endinput' >> T1$TNAME.fd ;
}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{trace}

\pdfmapfile{=\tname.map}

\usepackage{fonttable}
\makeatletter
\def\myfontinfo{font: encoding \f@encoding, family: \f@family, series: \f@series, shape: \f@shape, size: \f@size, baselineskip: \f@baselineskip}

\def\insertMyGlyphEZeroTwoFive{%
  \let\old@ffamily\f@family%
  \fontencoding{T1}\fontfamily{\tname}\selectfont%
  \char"0B% glyph 11=0x0B (was /cedilla, now /uniE025)
  \let\f@family\old@ffamily\selectfont%
}
\makeatother

\begin{document}

  \myfontinfo
  \vspace{-2em}
  %% \xfonttable{ encoding }{ family }{ series }{ shape }
  \makeatletter
    \xfonttable{\f@encoding}{\f@family}{\f@series}{\f@shape}
  \makeatother

  \clearpage

  Just testing normal font, and my glyph \insertMyGlyphEZeroTwoFive{} in between;\\
  \footnotesize% just to make small enough to fit on one page
  \fontencoding{T1}\fontfamily{\tname}\selectfont
  \myfontinfo
  \vspace{-2em}
  \makeatletter
    \xfonttable{\f@encoding}{\f@family}{\f@series}{\f@shape}
  \makeatother

\end{document}

相关内容