Показывать символы Юникода в PostScript - PullRequest
0 голосов
/ 23 февраля 2019

Как мне заставить мою программу PostScript отображать символ G clef из шрифта Bravura ?Согласно этому документу SMuFL кодовая точка Unicode для G (тройного) ключа в Bravura равна U + E050 (см. Стр. 48 Ключи (U + E050 – U + E07F)).Имя глифа PostScript может быть gClef (не уверен).

Вот моя лучшая попытка получить символы Юникода на странице.Я использую 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

1 Ответ

0 голосов
/ 23 февраля 2019

Первый вопрос: как вы определяете Бравуру и Калибри?Эти шрифты не являются частью стандартной установки Ghostscript, поэтому они должны быть добавлены некоторым образом, возможно, через fontconfig (в Linux), но я вижу, что вы используете Windows (из пути).Как вы добавили шрифты?

Теперь вы (опять же из сообщений обратного канала) загружаете шрифты TrueType и используете их в качестве замены отсутствующих шрифтов PostScript.Это нестандартная функция, поэтому Ghostscript приходится много гадать, чтобы попытаться создать шрифт Type 42 (шрифт PostScript с контурами TrueType) из шрифта TrueType.Нет никаких гарантий, что все получится правильно, хотя в наши дни это довольно хорошо.

Кстати, это не имеет ничего общего с Unicode: -)

В PostScript вы используете символкод для каждого символа, который вы хотите отобразить.В вашем случае вы использовали от 0x40 (@) до 0x4C (L) последовательно.При рендеринге глифа интерпретатор берет код символа и ищет кодировку в этой позиции.Обратите внимание, что ваши массивы кодирования содержат только записи от 0x41 до 0x47, поэтому коды от 0x48 до 0x4C будут неопределенными.

Давайте подумаем о вашем TextFont, то есть Calibri.В позиции 0x41 в кодировке у вас есть глиф с именем «Scaron».Поэтому интерпретатор обращается к словарю CharStrings со шрифтом.Словарь CharStrings содержит пары ключ / значение, ключ (в данном случае) - это имя, а значение - исполняемая программа, определяющая способ визуализации глифа.

Таким образом, интерпретатор ищет ключ с именем /Scaron в словаре CharStrings, а затем выполняет связанную с ним программу.Если он не может найти ключ / Scaron, он ищет ключ /.notdef (для всех шрифтов требуется , чтобы иметь .notdef) и выполняет его вместо этого.

У вас естьна самом деле не сказал, что вы выходите.Я предполагаю, что есть проблема, потому что вы опубликовали вопрос (который, кажется, не содержит никаких реальных вопросов ....), но вы не сказали, что это такое.Если вместо ожидаемого глифа вы получаете пустые прямоугольники, то это потому, что интерпретатор выполняет /.notdef, который для шрифтов TrueType часто является прямоугольником (шрифты PostScript часто имеют полностью пустой .notdef, но оба типа шрифтов могут иметь все, что ониwant)

В этом случае проблема в том, что вы используете имя глифа (например, / muscialnote), которого нет в словаре CharStrings.Если шрифт TrueType не имеет таблицы POST (в большинстве случаев нет), то это неудивительно, потому что /icalnote - это очень нестандартное имя для глифа.

Если я добавлю 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, что является зарезервированным GID TrueType для глифа .notdef, поэтому все эти имена будут сопоставлены с .notdef.

Я также вижу ряд записей, таких как:

4 / A

Это (очевидно) глифы, которые вы можете использовать, в данном случае карты name / Aв GID 4. При проверке выходных данных нет названия «quarternote», «музыкальная нота» и т. д. Существует Scaron, поэтому я ожидаю, что ваш символ «@» будет отображаться как заглавная буква S с акронитным акцентом.Оставшиеся глифы будут отображаться как пустые квадраты или вообще ничего.Тестирование здесь показывает (интересно) прямоугольник с вопросительным знаком в нем.

Теперь может случиться так, что шрифт Calibri содержит нужные глифы, если он есть, то, боюсь, единственный способ получить к ним доступ (из PostScript) - это определить имя, которое Ghostscript связывает с глифом.То же самое верно и для шрифта Bravura.

Небольшое программирование на PostScript (кажется, вы более чем компетентны в написании этого) позволит вам извлечь словарь CharStrings из шрифта, выполнить итерацию по нему и создатьмассив всех имен, которые имеют ненулевое значение.Затем вы можете распечатать страницу (возможно, много страниц), где вы печатаете именной глиф из шрифта, и под ним выведите имя, связанное с этим глифом.Вот ваша карта, теперь вы можете создать кодировку, которая отображает имя глифа на код символа, который вы хотите использовать в своей программе PostScript для рисования этого глифа.

FWIW, когда я пытаюсь использовать Bravura (который является OpenTypeшрифт, а не шрифт TrueType) Я получаю синтаксическую ошибку при загрузке шрифта.То же самое для BravuraText.

...