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

问题描述

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

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

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

此后记代码

   !PS
   /ArialMT findfont
   12 scalefont setfont
   72 72 moveto
   <26> show
   showpage
当我通过Adobe distiller运行

时,它会生成“&”号系统。看来,后记认情况下可以理解UTF-8编码的Unicode。

我不能用 club 符号做同样的事情。

我的研究表明,我必须使用 字符编码 ,而我迷路了。

有什么好心的人可以告诉我(希望很短)如何使用 字符编码 显示 club 符号吗?

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

阅读参考手册会让我头疼。

解决方法

尽管有多种处理方法,但PostScript根本不理解Unicode,或者至少不理解Unicode。

PostScript语言参考手册的5.3节包含有关字符编码的完整信息。您确实需要详细阅读此内容,您要问的是一个看似简单的问题,没有简单的答案。

此PostScript字体的工作方式是文档中的字符具有介于0到255之间的字符代码。在处理文本时,解释器将使用字符代码并在字体所附的Encoding中对其进行查找。如果您没有为字体提供编码,那么它通常会具有预定义的StandardEncoding。

对于字符代码0x7F及以下版本,StandardEncoding与UTF-8具有一定的一致性,但是我认为这并不完全相同。

编码将字符代码映射为字形名称,例如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字体,但这涉及猜测附加信息,并且没有真正的方法预先告知任何给定的解释器将如何处理。我怀疑Adobe Distiller的行为将类似于Ghostscript,并尝试将type42映射到StandardEncoding。

本质上,编码将字符代码映射到CharStrings词典中的键,并且与该键关联的值是GID。 GID用于以TrueType字体索引GLYF表,然后TrueType光栅化器读取该字形程序。

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

您将必须确定Encoding and CharStrings词典使用的是哪种键。它可能是名称,也可能是整数或其他任何东西。您可以通过查看Encoding数组的内容来弄清楚这一点。

老实说,除非您对TrueType字体了解很多,否则我认为您很难对字体进行反向工程以检索正确的GID,然后重新编码由解释程序加载的字体。您还需要检查findfont返回的字体字典的内容,以查看现有的映射是什么。至关重要的是,您可能需要修改CharStrings字典以将键映射到GID。 Distiller可能会返回一个字典,该字典被定义为“禁止访问”,这将阻止您查看内部或(或至少在其中的内部)。如果CharStrings词典已经为字体中的每个字形包含一个键,那么您可能可以不用看字体字典中的Encoding并对其进行修改。

我也许可以通过Ghostscript指导您完成此操作,但是我不知道Adobe Distiller如何定义从磁盘加载的TrueType字体。

您可以改用CIDFont。这些定义在5.11.1节中,并且可能是,如果您要使用预定义的Identity-H或UCS2 CMap之类的东西,则可以使用TrueType轮廓创建一个ArialMT的CID键控实例,该实例适用于Unicode代码点。

但这将意味着您自己定义字体,因此您需要将整个TrueType字体包含在PostScript程序中。同样,这并不简单。

,

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

我也有ArialMT.ttf,并制作了ArialMT.ttf.t42只是为了查看内部。我找到了KenS所描述的GID 389的/ club字形,并按照链接中的描述进行了尝试,并取得了很好的效果:

%!
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 字符。

这是一个完整的文件.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 https://stackoverflow.com/questions/54840594/show-unicode-characters-in-postscript
% 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 \377\001C\377\000 a part of the string.) show

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

showpage
%%EOF

产生这个 snapshot

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