在 PostScript 中显示 Unicode 字符 [英] Show Unicode characters in PostScript

查看:83
本文介绍了在 PostScript 中显示 Unicode 字符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何让我的 PostScript 程序显示来自 Bravura 字体的 G 谱号字符?根据这个 SMuFL 文档,G(高音)谱号的 Unicode 代码点在 Bravura 中是 U+E050(参见第 48 页谱号 (U+E050–U+E07F)).PostScript 字形名称可能是 gClef(不确定).

How do I get my PostScript program to show G clef character from Bravura font? According to this SMuFL document the Unicode code point for a G (treble) clef in Bravura is U+E050 (see page 48 Clefs (U+E050–U+E07F)). The PostScript glyph name might be gClef (not sure).

到目前为止,这是我在页面上获取 unicode 字符的最佳尝试.我正在使用 GhostScript 9.25 生成 PDF.这是 GhostScript 的输出:

Here is my best attempt so far to get the unicode characters on page. I am using GhostScript 9.25 to produce a PDF. This is the output from GhostScript:

GPL Ghostscript 9.25 (2018-09-13)
Copyright (C) 2018 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
Scanning C:/Windows/Fonts for fonts... 550 files, 358 scanned, 337 new fonts.
Can't find (or can't open) font file %rom%Resource/Font/Calibri.
Can't find (or can't open) font file Calibri.
Loading Calibri font from C:/Windows/Fonts/calibri.ttf... 8525920 7081126 4118548 2767358 1 done.
Can't find (or can't open) font file %rom%Resource/Font/BravuraText.
Can't find (or can't open) font file BravuraText.
Loading BravuraText font from C:/Windows/Fonts/BravuraText.otf... 9545496 7985907 8185868 6762307 1 done.
GPL Ghostscript 9.25: Can't embed the complete font BravuraText as it is too large, embedding a subset.
Main

这是最小的 PostScript 程序:

And this is the minimal PostScript program:

%!PS-Adobe-3.0
%%Title: unicode.ps
%%LanguageLevel: 3
%%EndComments


%%BeginProlog

userdict begin

%%EndProlog


%%BeginSetup

/mm { 25.4 div 72 mul } bind def
/A4Landscape [297 mm 210 mm] def
/PageSize //A4Landscape def
<< /PageSize PageSize >> setpagedevice


% ‘‘ReEncodeSmall’’ generates a new re-encoded font. It
% takes 3 arguments: the name of the font to be
% re-encoded, a new name, and an array of new character
% encoding and character name pairs (see the definition of
% the ‘‘scandvec’’ array below for the format of this
% array). This method has the advantage that it allows the
% user to make changes to an existing encoding vector
% without having to specify an entire new encoding
% vector. It also saves space when the character encoding
% and name pairs array is smaller than an entire encoding
% vector.

% Usage: /Times-Roman /Times-Roman-Scand scandvec 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


/Calibri /TextFont [
    16#41   /Scaron     % A (/Scaron Š U+0160)
    16#42   /quarternote                % B U+2669
    16#43   /musicalnote                % C
    16#44   /eighthnotebeamed           % D
    16#45   /musicalnotedbl             % E
    16#46   /beamedsixteenthnotes       % F
    16#47   /musicflatsign              % G
    16#47   /musicsharpsign             % H U+266F
] new-font-encoding

% https://github.com/steinbergmedia/bravura
% The Unicode code point for a G (treble) clef in Bravura Text is U+E050
% http://www.smufl.org/files/smufl-0.9.pdf
% p48 Clefs (U+E050–U+E07F)
% U+E050 (and U+1D11E) gClef G clef 
% http://www.jdawiseman.com/papers/trivia/character-entities.html
/Bravura /MusicFont [
    16#41   /gClef                      % A
    16#42   /quarternote                % B U+2669
    16#43   /musicalnote                % C
    16#44   /eighthnotebeamed           % D
    16#45   /musicalnotedbl             % E
    16#46   /beamedsixteenthnotes       % F
    16#47   /musicflatsign              % G
    16#47   /musicsharpsign             % H U+266F
] new-font-encoding

/MusicFont findfont 48 scalefont setfont

%%EndSetup


%%BeginScript

%% Main
(Main\n) print
<<>>begin
    /TextFont findfont 48 scalefont setfont
    0 setgray
    72 72 moveto
    (@ABCDEFGHIJKL) show

    0 72 translate

    /MusicFont findfont 48 scalefont setfont
    0 setgray
    72 72 moveto
    (@ABCDEFGHIJKL) show
end
showpage

%%EndScript

%%Trailer
%%EOF

推荐答案

第一个问题是您如何定义 Bravura 和 Calibri.这些字体不是标准 Ghostscript 安装的一部分,因此必须以某种方式添加它们,可能通过 fontconfig(在 Linux 上),但我看到您使用的是 Windows(从路径名).你是如何添加字体的?

The first question is how you are defining Bravura and Calibri. These fonts are not part of the standard Ghostscript installation, so they must be added in some fashion, possibly via fontconfig (on Linux), but I see you are using Windows (from the path name). How have you added the fonts ?

现在您(再次从后台消息)加载 TrueType 字体并将它们用作丢失的 PostScript 字体的替代品.这是一个非标准功能,因此 Ghostscript 必须进行大量猜测才能尝试从 TrueType 字体创建 Type 42 字体(带有 TrueType 轮廓的 PostScript 字体).不能保证它会做对,尽管现在已经很不错了.

Now you are (again from the back channel messages) loading TrueType fonts and using them as substitutes for missing PostScript fonts. That's a non-standard feature, so Ghostscript has to do a lot of guessing in order to try and create a Type 42 font (PostScript font with TrueType outlines) from a TrueType font. There's no guarantee it'll get it right, though it is pretty good these days.

顺便说一下,这与 Unicode 无关:-)

By the way, this is nothing to do with Unicode :-)

在 PostScript 中,您为要显示的每个字符使用一个字符代码.在您的情况下,您已连续使用 0x40 (@) 到 0x4C (L).渲染字形时,解释器获取字符代码,并在该位置查找编码.请注意,您的编码数组仅包含从 0x41 到 0x47 的条目,因此代码 0x48 到 0x4C 将是未定义的.

In PostScript you use a character code for each character you want to display. In your case you have used 0x40 (@) to 0x4C (L) consecutively. When rendering the glyph, the interpreter takes the character code, and looks up the Encoding at that position. Note that your Encoding arrays only contain entries from 0x41 to 0x47, so codes 0x48 to 0x4C will be undefined.

让我们考虑一下您的TextFont",即 Calibri.在编码中的位置 0x41,您有一个字形名称Scaron".因此,解释器随后会查阅字体的 CharStrings 字典.CharStrings 字典包含键/值对,键(在本例中)是名称,值是定义如何呈现字形的可执行程序.

Lets think about your 'TextFont', which is Calibri. At position 0x41 in the Encoding you have a glyph name 'Scaron'. So the interpreter then consults the CharStrings dictionary of the font. The CharStrings dictionary contains key/value pairs, the key (in this case) is a name, and the value is an executable program which defines how to render the glyph.

因此解释器在 CharStrings 字典中查找名为/Scaron 的键,然后执行与之关联的程序.如果它找不到键/Scaron,则查找键/.notdef(所有字体要求具有 .notdef)并执行该键.

So the interpreter looks for a key called /Scaron in the CharStrings dictionary, and then executes the program associated with it. If it can't find the key /Scaron, then it looks up the key /.notdef (all fonts are required to have a .notdef) and executes that instead.

你实际上并没有说出你要发表的内容.我假设存在问题,因为您已经发布了一个问题(似乎不包含任何实际问题....)但您没有说明问题是什么.如果你得到的是空心矩形而不是预期的字形,那是因为解释器正在执行/.notdef,对于 TrueType 字体来说,它通常是一个矩形(PostScript 字体通常有一个完全空白的 .notdef,但两种字体类型都可以有任何它们想要)

You haven't actually said what you're getting out. I'm assuming there's a problem, because you've posted a question (which doesn't seem to contain any actual questions....) but you have't said what it is. If you are getting hollow rectangles instead of the expected glyph, then that's because the interpreter is executing the /.notdef which for TrueType fonts is often a rectangle (PostScript fonts often have a completely blank .notdef, but both font types can have anything they want)

在这种情况下,问题在于您使用了 CharStrings 字典中不存在的字形名称(例如/muscialnote).除非 TrueType 字体有 POST 表(大多数没有),否则这并不奇怪,因为/musicalnote 是一个非常不标准的字形名称.

In which case the problem is that you are using a glyph name (eg /muscialnote) which doesn't exist in the CharStrings dictionary. Unless the TrueType font had a POST table (most do not) then that's not surprising, because /musicalnote is a very non-standard name for a glyph.

如果我将 Calibri 添加到 fontmap.GS 然后执行:

If I add Calibri to fontmap.GS and then do:

%!
/Calibri findfont /CharStrings get {== ==} forall

然后我看到许多表单条目:

0/_67560/_6689

0 /_6756 0 /_6689

这些将名称(例如/_6576)映射到 TrueType GID.使用 TrueType 字体时,Ghostscript 需要 GID,以便它可以从 GLYF 表中找到字体中的字形程序.当定义 TrueType 字体用作 type 42 时,这是 Ghostscript 必须尝试为自己创建的东西(一个真正的 Type 42 字体是用这个字典定义的,作为字体的一部分).它如何实现这一点是启发式的,即它会猜测很多.

these are mapping the names (eg /_6576) to the TrueType GID. When using a TrueType font Ghostscript needs the GID so that it can find the glyph program in the font from the GLYF table. When defining a TrueType font for use as a type 42, this is somethign Ghostscript has to try and create for itself (a real Type 42 font is defined with this dictionary as part of the font). How it achieves this is heuristic, ie it guesses a lot.

在这种情况下,GID 为 0,这是 TrueType 为 .notdef 字形保留的 GID,因此这些名称都将映射到 .notdef.

In this case the GID is 0, which is the TrueType reserved GID for the .notdef glyph, so these names will all map to the .notdef.

我还看到了一些条目,例如:

I also see a number of entries like:

4/A

这些(显然)是您可以使用的字形,在这种情况下,名称/A 映射到 GID 4.检查输出,没有名称四分音符"、音乐音符"等.有一个 Scaron,所以我期望您的 '@' 字符将呈现为带有卡隆口音的大写 S.剩余的字形将呈现为空方块,或者什么也不呈现.此处的测试显示(有趣的是)一个带有问号的矩形.

These (obviously) are the glyphs that you can use, in this case the name /A maps to GID 4. Checking the output, there is no name 'quarternote, 'musicalnote' etc. There is an Scaron, so I expect that your '@' character will render as a capital S with a caron accent. The remaining glyphs will render as empty squares, or nothing at all. Testing here shows (interestingly) a rectangle with a question mark in it.

现在可能是 Calibri 字体包含您想要的字形,如果确实如此,那么恐怕访问它们的唯一方法(从 PostScript)是识别与字形关联的 Ghostscript 的名称.Bravura 字体也是如此.

Now it may be that the Calibri font contains the glyphs you want, if it doe, then I'm afraid the only way to access them (from PostScript) is to identify the name that Ghostscript associated with the glyph. The same is true of the Bravura font.

一点 PostScript 编程(似乎你完全有能力写这个)可以让你从字体中检索 CharStrings 字典,遍历它,并构建一个包含所有非零名称的数组价值.然后,您可以打印一个页面(可能是许多页面),在其中打印字体中的命名字形,并在其下打印与该字形关联的名称.这是您的映射,现在您可以构建一个编码,将字形名称映射到您要在 PostScript 程序中使用的字符代码来绘制该字形.

A little PostScript programming (seems like you're more than competent to write this) would allow you to retrieve the CharStrings dictionary from the font, iterate through it, and build an array of all the names which have a non-zero value. You could then print a page (probably many pages) where you print a named glyph from the font, and under it print the name associated with that glyph. There's your map, now you can build an Encoding which maps the glyph name to the character code you want to use in your PostScript program to draw that glyph.

FWIW 当我尝试使用 Bravura(这是一种 OpenType 字体,而不是 TrueType 字体)时,我在加载字体时遇到语法错误.BravuraText 也是如此.

FWIW when I try to use Bravura (which is an OpenType font, not a TrueType font) I get a syntax error whie loading the font. Same for BravuraText.

这篇关于在 PostScript 中显示 Unicode 字符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆