在PostScript中显示Unicode字符

问题描述 投票:1回答:1

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

到目前为止,这是我在页面上获取unicode字符的最佳尝试。我正在使用GhostScript 9.25生成PDF。这是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程序:

%!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
unicode postscript lang
1个回答
2
投票

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

现在你(再次从后面的频道消息)加载TrueType字体并使用它们代替丢失的PostScript字体。这是一个非标准功能,因此Ghostscript必须进行大量猜测才能尝试从TrueType字体创建Type 42字体(带有TrueType轮廓的PostScript字体)。虽然现在还不错,但并不能保证它能够做到正确。

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

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

让我们想想你的'TextFont',它是Calibri。在编码中的位置0x41处,您有一个字形名称'Scaron'。因此,解释器然后查询字体的CharStrings字典。 CharStrings字典包含键/值对,键(在本例中)是名称,值是可执行程序,它定义如何呈现字形。

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

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

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

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

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

然后我看到表格的许多条目:

0 /_6756 0 /_6689

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

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

我还看到一些条目,如:

4 / A.

这些(显然)是你可以使用的字形,在这种情况下,名称/ A映射到GID 4.检查输出,没有名称'quarternote','audionote'等等。有一个Scaron,所以我希望你的'@'字符将呈现为具有caron口音的大写字母S.剩余的字形将呈现为空方块,或者根本不呈现。这里的测试显示(有趣的是)一个带有问号的矩形。

现在可能是Calibri字体包含你想要的字形,如果它,那么我担心访问它们的唯一方法(来自PostScript)是识别Ghostscript与字形相关联的名称。 Bravura字体也是如此。

一个小的PostScript编程(看起来你有能力写这个)将允许你从字体中检索CharStrings字典,遍历它,并构建一个具有非零值的所有名称的数组。然后,您可以打印一个页面(可能是许多页面),从该字体打印命名字形,然后在其下打印与该字形关联的名称。有你的地图,现在你可以建立一个编码,它将字形名称映射到你想在PostScript程序中使用的字符代码来绘制该字形。

FWIW当我尝试使用Bravura(OpenType字体,而不是TrueType字体)时,加载字体时出现语法错误。 BravuraText也是如此。

© www.soinside.com 2019 - 2024. All rights reserved.