显示 Unicode 高于十进制 256 的字形

Showing glyphs with Unicodes higher than decimal 256

我正在寻求有关从后记中的 Arial 字体打印 club 符号的帮助。

它的 Unicode 为 9827(2663 十六进制)。

& 符号是 Unicode 38(26 十六进制)

此后记代码片段

   !PS
   /ArialMT findfont
   12 scalefont setfont
   72 72 moveto
   <26> show
   showpage

当我通过 Adob​​e Distiller 运行 生成符号系统时。 postscript 似乎默认理解使用 UTF-8 编码的 Unicode。

我无法对 club 符号执行相同的操作。

我的研究表明我必须使用 字符编码 而这正是我迷路的地方。

哪位好心人可以告诉我(希望相当简短)如何使用 字符编码 显示 club 符号?

或者,如果您能给我一个简单的教程,我们将不胜感激。

阅读参考手册让我头晕目眩。

PostScript 不理解 Unicode,根本不理解,或者至少不作为标准,尽管有一些方法可以处理它。

PostScript 语言参考手册的第 5.3 节包含有关字符编码的完整信息。你真的需要详细阅读这篇文章,你问的是一个看似简单的问题,没有简单的答案。

PostScript 字体的工作方式是文档中的字符有一个介于 0 和 255 之间的字符代码。在处理文本时,解释器获取字符代码并在附加到字体。如果您没有为字体提供编码,那么它通常会有一个 pre-defined StandardEncoding。

对于字符代码 0x7F 及以下,StandardEncoding 与 UTF-8 有一些一致性,但我认为它并不完全相同。

Encoding 将字符代码映射到字形名称,例如 StandardEncoding 中的 0x41 映射到 /A(这是 PostScript 中的名称)。请注意,这不是 UTF-8 或其他任何东西,它是一个映射。将第一个字符映射到字符代码 1,第二个字符映射到字符代码 2,依此类推,这是完全可能的,也是子集字体的常见做法。

因此,如果我们将该方案应用于 'Hello World',我们将使用映射

的编码
0x01->/H
0x02->/e
0x03->/l
0x04->/o
0x05->/space
0x06->/W
0x07->/r
0x08->/d

然后我们可以通过 :

绘制文本
<0102030304050604070308> show

如您所见,这与 UTF-8 完全无关。

无论如何,在检索到字形名称后,解释器会查看字体中的 CharStrings 字典并找到与字符代码关联的键。因此,对于 StandardEncoding,我们会将 0x41 映射到 /A,然后在 CharStrings 字典中查找 /A 键。然后我们获取与该键关联的值,它将是一个 PostScript 字形程序和 运行 它。

您的问题是您正在尝试使用 TrueType 字体。 PostScript 不以这种方式支持 TrueType 字体,当它们被定义为 Type42 字体时它确实支持它们,因为 Type42 字体带有一些附加信息,这些信息允许 PostScript 解释器以与 PostScript 字体相同的方式对待它们。

许多现代 PostScript 解释器会加载 TrueType 字体并从中为您创建 Type42 字体,但这涉及到猜测附加信息,并且没有真正的方法可以提前告诉任何给定的解释器将如何处理这个.我怀疑 Adob​​e Distiller 的行为与 Ghostscript 类似,并尝试将 type42 映射到 StandardEncoding。

本质上,Encoding 将字符代码映射到 CharStrings 字典中的一个键,与该键关联的值是 GID。 GID 用于索引 TrueType 字体中的 GLYF table,然后 TrueType 光栅器读取该字形程序。

因此,为了创建带有将字符代码映射到俱乐部符号的编码的 type42 字体,您需要知道字体中俱乐部符号的 GID 实际上是什么。这可以从 TrueType 字体中的 CMAP subtables 之一派生,这就是 PostScript 解释器(如 Ghostscript)在将 TrueType 字体作为 Type 42 加载时构建所需编码的方式。然后您需要更改type42 字体中的 CharStrings 字典,以便它映射到正确的 GID。您还需要更改编码;选择您要使用的字符代码,将字符代码映射到 CharStrings 字典中的键。

您必须确定 Encoding 和 CharStrings 字典使用的是哪种键。它可能是名称,也可能是整数或其他任何东西。您当然可以通过查看编码数组的内容来解决这个问题。

老实说,除非您对 TrueType 字体了解很多,否则我认为您很难 reverse-engineer 字体来检索正确的 GID,然后 re-encode 加载的字体口译员。您还需要检查 findfont 返回的字体字典的内容以查看现有映射是什么。至关重要的是,您可能需要修改 CharStrings 字典以将键映射到 GID。可能是 Distiller returns 定义为 no-access 的字典会阻止您查看内部或(或至少,它的内部部分)。如果 CharStrings 字典已经为字体中的每个字形包含一个键,那么您可能可以通过查看字体字典中的编码并对其进行修改来逃脱,它可能会这样做。

我可能会指导您使用 Ghostscript 完成此操作,但我不知道 Adob​​e Distiller 如何定义从磁盘加载的 TrueType 字体。

您可以改用 CIDFont。这些在第 5.11.1 节中定义,如果您要使用 pre-defined Identity-H 或 UCS2 CMap 之类的东西,您可以创建 ArialMT 的 CID-Keyed 实例,其中包含 TrueType 轮廓将适用于您的 Unicode 代码点。

但这意味着您需要自己定义字体,因此您需要将整个 TrueType 字体作为 PostScript 程序的一部分。这又不简单。

这里有一些很好的信息:Show Unicode characters in PostScript

我也有 ArialMT.ttf 并制作了 ArialMT.ttf.t42 只是为了看看里面。我按照 KenS 的描述找到了 GID 为 389 的 /club 字形,并按照链接 post 中的描述进行了尝试,结果很好:

%!
100 300 moveto
/ArialMT.ttf 46 selectfont (ArialMT) show
100 200 moveto /club glyphshow
showpage

注意:我使用 ArialMT.ttf 因为 TT 字体没有安装在当前目录中的 ghostscript Fontmap 中,因此使用 gs -P 出于这个原因。当 TT 字体已安装在搜索路径中时,正常的 /ArialMT findfont 应该可以工作。这是我第一次尝试使用这些字形,只是在反复试验。

有一个全面的 Adob​​e 字形列表,映射了许多 Unicode 字符:https://github.com/adobe-type-tools/agl-aglfn/blob/master/glyphlist.txt

如果所需的 Unicode 字符在该列表中,请说 club;2663clubsuitblack;2663clubsuitwhite;2667,所有需要说的是 /club glyphshow 大多数现代字体都知道该怎么做。但是 @KenS 说这“可能会导致问题”。


相反,推荐参考中出现的首选方案是:
  • 在序言中创建一个复合字体,每个字体一个 您正在使用;

  • 将低 256 个字符包含为 Font0;

  • 将您计划使用的任何 Unicode 字符添加到块中 256个字符,如Font1、Font2等;

  • 将特殊字符的Unicode重新映射为双字符 复合字体中子字体索引的顺序,后跟 通过作为该子字体中字符索引的字节。

以下是两种方法的完整示例。

我使用 http://www.acumentraining.com/Acumen_Journal/AcumenJournal_May2002.zip,但 Font1 是与 Font0 相同字体的一部分的自定义重新映射,重新使用一些众所周知的 ascii 字符。

这是一个完整的 file.eps:

%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 0 0 792 612
%%LanguageLevel: 2
%%EndComments
%%BeginProlog
userdict begin
%%EndProlog

%%BeginSetup
% The following encodes a few useful Unicode glyphs, if only a few are needed.
% Based on 
% Usage: /Times-Roman /Times-Roman-Uni UniVec new-font-encoding

/new-font-encoding { <<>> begin
    /newcodesandnames exch def
    /newfontname exch def
    /basefontname exch def
    /basefontdict basefontname findfont def     % Get the font dictionary on which to base the re-encoded version.
    /newfont basefontdict maxlength dict def    % Create a dictionary to hold the description for the re-encoded font.
    basefontdict
        { exch dup /FID ne                      % Copy all the entries in the base font dictionary to the new dictionary except for the FID field.
            { dup /Encoding eq
                { exch dup length array copy    % Make a copy of the Encoding field.
                    newfont 3 1 roll put }
                { exch newfont 3 1 roll put }
                ifelse
            }
            { pop pop }                         % Ignore the FID pair.
            ifelse
        } forall
    newfont /FontName newfontname put           % Install the new name.
    newcodesandnames aload pop                  % Modify the encoding vector. First load the new encoding and name pairs onto the operand stack.
    newcodesandnames length 2 idiv
        { newfont /Encoding get 3 1 roll put}
        repeat                                  % For each pair on the stack, put the new name into the designated position in the encoding vector.
    newfontname newfont definefont pop          % Now make the re-encoded font description into a POSTSCRIPT font.
                                                % Ignore the modified dictionary returned on the operand stack by the definefont operator.
end} def

/Helvetica /Helvetica-Uni [
    16#43  /club        % ASCII 43 = C = /club
] new-font-encoding

/Helv
<<
   /FontType 0
   /FontMatrix [ 1 0 0 1 0 0 ]
   /FDepVector [
      /Helvetica findfont        % this is Font0
      /Helvetica-Uni findfont    % this is Font1
      ]
   /Encoding [ 0 1 ]
   /FMapType 3
>> definefont pop
%%EndSetup

%%BeginScript

/Helv 20 selectfont
72 300 moveto
(The club character is 7[=10=]1C7[=10=]0 a part of the string.) show

/Helvetica findfont 20 scalefont setfont
263 340 moveto
/club glyphshow

showpage
%%EOF

产生这个

显然,这可以扩展到更多字符,但每个子字体只有 256 个。我不知道这种重新编码的“标准”约定,尽管我可以想象一组希腊字母 alpha、beta、gamma ......会很明显地映射到 a、b、c ......也许其他人是知道 Adobe glyph list 中所有 Unicode 字符的此类实现使用多个自定义子字体,并且可以提供一个指针..