Как в Solaris 2 создать шрифты Type1 с кодировкой koi8, cp1251, cp866 пользуясь только текстовым редактором

Нижеследующая информация в основном предназначена для тех, кто работает под Solaris версии > 2.5.

В конференциях часто встречаются вопросы о подключении шрифтов в различных кодировках (koi8, cp1251, cp866...) к X11, Display PostScript, Netscape и т.д.

Обычно применяемый способ решения - скачивание дополнительных шрифтов в формате bitmap с какого-либо сервера. Однако, если на Вашем компьютере установлен пакет русской локализации и, тем самым, русские буквы уже есть, то существует простой способ, позволяющий "на лету" создавать масштабируемые шрифты Type1 с любым расположением букв в таблице и, следовательно, в любой кодировке.

Решение основано на том, что для языка PostScript шрифт Type1 всего лишь программа, определяющая содержимое так называемого словаря шрифта и содержащая внутри себя локальные подпрограммы вычерчивания символов. Словарь состоит из некоторого количества пар типа ключ - значение. Значениями элементов словаря могут быть любые объекты языка, в том числе и другие словари. В словаре шрифта Type1 имеются семь обязательных элементов с ключами:

FontType
FontMatrix
Encoding
FontBBox
PainType
Private
CharStrings

Исследовав с помощью текстового редактора любой шрифт Type1, Вы легко найдете эти элементы, за исключением элемента CharStrings, который находится в зашифрованной части файла шрифта (после оператора eexec).

Кроме вышеперечисленных, имеется также целый ряд вспомогательных элементов словаря. Эти элементы, как правило, служат для облегчения установки шрифта в системе или используются прикладными программами для увеличения производительности при работе со шрифтами.

В Solaris 2.5.1, на котором установлена русская локализация, имеется пример ($OPENWINHOME/lib/locale/ru/X11/fonts/Type1/outline/HelveticaCyr.ps), который мы сейчас и рассмотрим, чтобы понять, как создаётся новый шрифт на базе уже имеющегося.

(1)	%!PS-AdobeFont-1.0: HelveticaCyr
(2)	%%Title: HelveticaCyr
(3)	%%BeginResource: font HelveticaCyr
(4)
(5)	/FullName (Helvetica Cyr) def
(6)	/FamilyName (Helvetica Cyr) def
(7)	/Weight (Medium) def
(8)	/ItalicAngle 0 def
(9)	/FontName /HelveticaCyr def
(10)	/ArialCyr findfont dup length dict dup % font dict dict
(11)	3 -1 roll				% dict dict font
(12)	{ 1 index /FID ne 2 index /UniqueID ne and
(13)		{ 2 index 3 1 roll put }
(14)		{ pop pop } ifelse
(15)	} forall
(16)
(17)	dup /FontName /HelveticaCyr put
(18)	/HelveticaCyr exch definefont pop
(19)
(20)	%%EndResource
(21)	%%EOF

В программе всего 21 строка. Пустые строки игнорируются. Строки, начинающиеся с %, это комментарии, за исключением строк, начинающихся с %%, которые служат инструкциями для интерпретатора PostScript.

Язык Postscript является операторным и использует стек для временного хранения операндов. По выполнении операции, её операнды с вершины стека удаляются, а результат, за исключением случаев когда он неявен, записывается на вершину стека. Операторы - это зарезервированные слова языка.

Таким образом строка (8) программы читается следующим образом: поместить литеральное имя ItalicAngle в стек, поместить число 0 в стек, выполнить оператор def. Результатом данной операции будет присвоение значения 0 переменной ItalicAngle, причем оба элемента, ранее помещённые в стек, будут удалены. Текстовые строки-константы заключаются не в кавычки, как в других языках, а в круглые скобки. После прочитанного, я думаю, у Вас не будет трудностей с пониманием строк (5) - (9).

В строке (10) встречаются новые операторы findfont, dup, length, dict и её следует понимать так: поместить литеральное имя ArialCyr на вершину стека, найти (возможно на диске по известным путям, а может быть получить от font-сервера) словарь шрифта ArialCyr и поместить этот словарь на вершину стека, сдублировать словарь на вершине стека для того, чтобы можно было определить его длину и не потерять сам словарь, определить длину словаря, т.е. количество его элементов, создать пустой словарь такой-же длины, для копирования в него исходного словаря и сдублировать этот словарь. После выполнения этой строки в стеке, как указано в комментарии, останутся три элемента: словарь шрифта и два пустых словаря.

Оператор roll в строке (11) расставляет элементы в стеке в порядке, необходимом для правильного выполнения оператора forall.

Оператор forall выполняет процедуру, т.е. группу операторов взятую в фигурные скобки и записанную в строках (12) - (14) для каждого элемента словаря, находящегося на вершине стека, помещая перед этим текущую пару элементов ключ - значение на вершину стека. Здесь и происходит копирование элементов словаря шрифта ArialCyr в пустой словарь. Элементы с ключами /FID и /UniqueID не копируются. /UniqueID служит для целей кеширования растризованных изображений символов и должен либо быть уникальным в системе, либо не задаваться вообще. При отсутствии /UniqueID кеширование всё-равно происходит, но, при удалении шрифта из виртуальной памяти PostScript, содержимое кеш теряется. /FID существует только в словаре шрифта над которым выполнен оператор definefont. Значение /FID формируется динамически самим PostScript.

Примечание: В документации фирмы Adobe Systems (PostScipt Language Reference Manual, Second Edition, глава 5.8) говорится, что "если Вы копируете словарь шрифта с целью создания модифицированного шрифта, то Вы не должны копировать UniqueID. Как исключение из этого общего правила приемлемо (и предпочтительно) оставлять оригинальный UniqueID, если модифицируются только FontName, FontInfo, FontMatrix или Encoding, т.к. эти изменения не влияют на метрику символов и их внешний вид". При этом, очевидно, уменьшатся затраты виртуальной памяти, необходимой для кеширования символов. Вы можете скорректировать цикл forall и проверить это самостоятельно.

В строке (17) в переменную /FontName вновь созданного словаря шрифта на место старого имени ArialCyr заносится новое имя HelveticaCyr. Конструирование шрифта завершается оператором definefont в строке (18) программы. Шрифт готов для использования.

Внимательный читатель может задать вопрос: для чего же служат строки (5) - (9), если значения переменных, определяемые в этих строках, нигде не используются? Действительно, без этих строк можно обойтись и поэтому ответ не очевиден. Эти строки необходимы для программы $OPENWINHOME/bin/makepsres, которая создаёт служебный файл, необходимый для подключения шрифта к системе Display PostScript. Программа makepsres анализирует все файлы на заданных путях поиска, извлекает из них информацию о найденных ресурсах PostScript и помещает её в PSres.upr.

Нашей задачей является создание шрифта в другой кодировке. Для этого в новом словаре необходимо подменить значение ключа /Encoding на новое. Это не трудно. Мы уже проделали аналогичную операцию над ключём /FontName в строке (17). В результате приходим к следующей программе:

%!PS-AdobeFont-1.0: ArialKoi8
%%Title: ArialKoi8
%%CreationDate: Птн 28 Ноя 1997 21:26:14 EET
%%BeginResource: font ArialKoi8

/FullName (Arial Koi8) def
/FamilyName (Arial Koi8) def
/Weight (Regular) def
/ItalicAngle 0 def
/FontName /ArialKoi8 def

/encoding_array 256 array def
0 1 127 { dup encoding_array exch dup StandardEncoding exch get put } for
128 1 255 { encoding_array exch /.notdef put } for
encoding_array
  dup 163 /afii10071 put %ё
  dup 179 /afii10023 put %Ё
  dup 184 /afii61352 put %№
  dup 192 /afii10096 put %ю
  dup 193 /afii10065 put %а
  dup 194 /afii10066 put %б
  dup 195 /afii10088 put %ц
  dup 196 /afii10069 put %д
  dup 197 /afii10070 put %е
  dup 198 /afii10086 put %ф
  dup 199 /afii10068 put %г
  dup 200 /afii10087 put %х
  dup 201 /afii10074 put %и
  dup 202 /afii10075 put %й
  dup 203 /afii10076 put %к
  dup 204 /afii10077 put %л
  dup 205 /afii10078 put %м
  dup 206 /afii10079 put %н
  dup 207 /afii10080 put %о
  dup 208 /afii10081 put %п
  dup 209 /afii10097 put %я
  dup 210 /afii10082 put %р
  dup 211 /afii10083 put %с
  dup 212 /afii10084 put %т
  dup 213 /afii10085 put %у
  dup 214 /afii10072 put %ж
  dup 215 /afii10067 put %в
  dup 216 /afii10094 put %ь
  dup 217 /afii10093 put %ы
  dup 218 /afii10073 put %з
  dup 219 /afii10090 put %ш
  dup 220 /afii10095 put %э
  dup 221 /afii10091 put %щ
  dup 222 /afii10089 put %ч
  dup 223 /afii10092 put %ъ
  dup 224 /afii10048 put %Ю
  dup 225 /afii10017 put %А
  dup 226 /afii10018 put %Б
  dup 227 /afii10040 put %Ц
  dup 228 /afii10021 put %Д
  dup 229 /afii10022 put %Е
  dup 230 /afii10038 put %Ф
  dup 231 /afii10020 put %Г
  dup 232 /afii10039 put %Х
  dup 233 /afii10026 put %И
  dup 234 /afii10027 put %Й
  dup 235 /afii10028 put %К
  dup 236 /afii10029 put %Л
  dup 237 /afii10030 put %М
  dup 238 /afii10031 put %Н
  dup 239 /afii10032 put %О
  dup 240 /afii10033 put %П
  dup 241 /afii10049 put %Я
  dup 242 /afii10034 put %Р
  dup 243 /afii10035 put %С
  dup 244 /afii10036 put %Т
  dup 245 /afii10037 put %У
  dup 246 /afii10024 put %Ж
  dup 247 /afii10019 put %В
  dup 248 /afii10046 put %Ь
  dup 249 /afii10045 put %Ы
  dup 250 /afii10025 put %З
  dup 251 /afii10042 put %Ш
  dup 252 /afii10047 put %Э
  dup 253 /afii10043 put %Щ
  dup 254 /afii10041 put %Ч
  dup 255 /afii10044 put %Ъ
pop

/ArialCyr findfont dup length dict dup
3 -1 roll
{ 1 index /FID ne 2 index /UniqueID ne 3 index /Encodind ne and and
	{ 2 index 3 1 roll put }
	{ pop pop } ifelse
} forall

dup /FontName /ArialKoi8 put
dup /Encoding encoding_array put
/ArialKoi8 exch definefont pop

%%EndResource
%%EOF

Изменяя в этом файле имена и атрибуты шрифтов и переставляя значения в таблице encoding_array можно получить шрифты с любыми именами и в любых кодировках.

Кроме файла шрифта можно сделать также файл Adobe Font Metrics (AFM). Наличие этого файла необязательно, но он, если есть, может быть использован некоторыми прикладными программами для того, чтобы быстро подсчитать геометрические размеры строки текста без отрисовки.

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

Для создания файла AFM можно использовать слегка доработанную программу printafm.ps из пакета GNU PostScript. Доработка заключается в том, что вместо встроенного оператора GNU PostsScript =only используется эквивалентная ему подпрограмма:

/=only { 256 string cvs print } bind def

и закомментированы несколько заключительных строк программы, в которых аргументы считывались из командной строки:

%!
% written by James Clark 
% print an afm file on the standard output
% usage is `fontname printafm' eg `/Times-Roman printafm'

% From the `dvitops' distribution, which included this notice:
% dvitops is not copyrighted; you can do with it exactly as you please.
% I would, however, ask that if you make improvements or modifications,
% you ask me before distributing them to others.

% Altered by d.love@dl.ac.uk to produce input for Rokicki's afm2tfm,
% which groks the format of the Adobe AFMs.

% Modified by L. Peter Deutsch 9/14/93:
%   uses Ghostscript's =only procedure to replace 'buf cvs print'.
% Modified by L. Peter Deutsch 9/6/95:
%   uses Ghostscript's shellarguments facility to accept the font name
%     on the command line.

/onechar 1 string def

% c toupper - c
/toupper {
	dup dup 8#141 ge exch 8#172 le and { 
		8#40 sub
	} if
} bind def

% printcharmetrics -

/printcharmetrics {
	(StartCharMetrics ) print
	currentfont /CharStrings get dup length exch /.notdef known
        { 1 sub } if =
	currentfont 1000 scalefont setfont 0 0 moveto
	/e currentfont /Encoding get def
	0 1 255 {
		dup e exch get
		dup /.notdef ne {
			exch dup printmetric
		} {
			pop pop
		} ifelse
	} for
	% s contains an entry for each name in the original encoding vector
	/s 256 dict def
	e {
		s exch true put
	} forall
	% v is the new encoding vector
	/v 256 array def
	0 1 255 {
		v exch /.notdef put
	} for
	% fill up v with names in CharStrings
	/i 0 def
	currentfont /CharStrings get {
		pop
		i 255 le {
			v i 3 -1 roll put
			/i i 1 add def
		} {
			pop
		} ifelse
	} forall
	% define a new font with v as its encoding vector
	currentfont maxlength dict /f exch def
	currentfont {
		exch dup dup /FID ne exch /Encoding ne and { 
			exch f 3 1 roll put
		} { 
			pop pop 
		} ifelse
	} forall
	f /Encoding v put
	f /FontName /temp put
	% make this new font the current font
	/temp f definefont setfont
	% print a entry for each character not in old vector
	/e currentfont /Encoding get def
	0 1 255 {
		dup e exch get
		dup dup /.notdef ne exch s exch known not and { 
			exch -1 printmetric
		} { 
			pop pop
		} ifelse
	} for
	(EndCharMetrics) =
} bind def

% name actual_code normal_code printmetric -

/printmetric {
	/saved save def
	(C ) print =only
	( ; WX ) print
	onechar 0 3 -1 roll put
	onechar stringwidth pop round cvi =only
	( ; N ) print =only
	( ; B ) print
	onechar false charpath flattenpath mark pathbbox counttomark {
		counttomark -1 roll
		round cvi =only
		( ) print
	} repeat pop
	(;) =
	saved restore
} bind def

% fontname printafm -

/printafm {
	findfont gsave setfont
	(StartFontMetrics 2.0) =
	(FontName ) print currentfont /FontName get =

		% Print the FontInfo

	currentfont /FontInfo get {
		exch
		=string cvs dup dup 0 get 0 exch toupper put print
		( ) print =
	} forall

		% Print the FontBBox

	(FontBBox) print
	currentfont /FontBBox get {
		( ) print round cvi =only
	} forall
	(\n) print

	printcharmetrics
	(EndFontMetrics) =
	grestore
} bind def

% Check for command line arguments.
%[ shellarguments
% { ] dup length 1 eq
%    { 0 get printafm }
%    { (Usage: printafm fontname\n) print flush }
%   ifelse
% }
% { pop }
%ifelse

/=only { 256 string cvs print } bind def

/ArialKoi8 printafm
quit

Запустить эту программу Вы можете через Display PostScript Executive:

cat printafm.ps | $OPENWINHOME/demo/dpsexec -noexec -root

Файл AFM будет записан на системный вывод. В него нужно добавить информацию о кернинге, взяв её из файла AFM от прототипа шрифта (ArialCyr).

Для подключения шрифта к X и Display PostScript необходимо создать файлы PSres.upr (программой $OPENWINHOME/bin/makepsres), fonts.alias и fonts.scale (вручную), fonts.dir (программой $OPENWINHOME/bin/mkfontdir).

К сожалению Display PostScript в Solaris 2.5.1 считает правильными только следующие значения Encoding - последнего поля шаблона имени шрифта (кто знает, как разубедить его в этом?):

0
1
5
8
dectech
dingbats
fontspecific
symbol

Нельзя приписать созданному нами шрифту ArialCyrKoi8 шаблон имени вида

-roy international-arial-*-*-*-*-*-*-*-*-*-*-koi8-r

т.к. Encoding "r" не входит в список допустимых. Также нельзя использовать шаблон

-roy international-arial-*-*-*-*-*-*-*-*-*-*-koi8-1

т.к. в Encoding "1" нет имён типа afii10093. Однако можно применить шаблон

-roy international-arial-*-*-*-*-*-*-*-*-*-*-koi8-5

Полученные шрифты не могут быть экспортированы программой fontserver (пока не знаю, что ей не хватает), поэтому их лучше поместить в отдельный каталог. Указанное замечание распространяется также на шрифт HelveticaCyr, который поставляется Sun Microsystems в пакете русской поддержки для Solaris 2.5.1.

Если Вы всё-же экспортируете подобные шрифты, то, при запросе шрифта со стороны клиента, программа fs будет постоянно "падать" и запускаться вновь (при запуске через inetd), а экран клиента "замёзнет".

В файл /var/adm/messages будет выдаваться сообщение:

Dec  4 17:04:12 vit inetd[110]: /usr/openwin/lib/fs.auto: Child Status Changed

Вы можете воспользоваться скриптом makecyrfonts.sh, который выполняет все операции создания семейств шрифтов koi8, cp866, cp1251 и подключения их к X11 и Display Postscript. Каждый новый шрифт занимает всего 2.5K дисковой памяти. Шрифты имеют следующие PostScript имена:

ArialCP1251
ArialCP1251-Bold
ArialCP1251-BoldItalic
ArialCP1251-Italic
ArialCP866
ArialCP866-Bold
ArialCP866-BoldItalic
ArialCP866-Italic
ArialKoi8
ArialKoi8-Bold
ArialKoi8-BoldItalic
ArialKoi8-Italic
CourierCP1251
CourierCP1251-Bold
CourierCP1251-BoldItalic
CourierCP1251-Italic
CourierCP866
CourierCP866-Bold
CourierCP866-BoldItalic
CourierCP866-Italic
CourierKoi8
CourierKoi8-Bold
CourierKoi8-BoldItalic
CourierKoi8-Italic
TimesNewRomanCP1251
TimesNewRomanCP1251-Bold
TimesNewRomanCP1251-BoldItalic
TimesNewRomanCP1251-Italic
TimesNewRomanCP866
TimesNewRomanCP866-Bold
TimesNewRomanCP866-BoldItalic
TimesNewRomanCP866-Italic
TimesNewRomanKoi8
TimesNewRomanKoi8-Bold
TimesNewRomanKoi8-BoldItalic
TimesNewRomanKoi8-Italic

Скрипт нужно выполнять имея привелегии пользователя root, т.к. в нём происходит создание подкаталога в каталоге $OPENWINHOME/lib/locale/ru/X11, а также запись в файл $OPENWINHOME/server/etc/OWconfig.

Модификация OWconfig производится программой $OPENWINHOME/demo/fpadd. Если у Вас не установлены программы из $OPENWINHOME/demo, то вначале установите их. В этом каталоге находятся несколько полезных программ для работы со шрифтами и дисплейным PostScript:

/usr/openwin/demo/dpsexec
/usr/openwin/demo/fontadd
/usr/openwin/demo/fontadmin
/usr/openwin/demo/fontls
/usr/openwin/demo/fontrm
/usr/openwin/demo/fpadd
/usr/openwin/demo/fpls
/usr/openwin/demo/fprm

Перед модификацией OWconfig он сохраняется под именем OWconfig.SAVE только в том случае, когда Вы выполняете скрипт в первый раз. Предыдущее значение OWconfig всегда сохраняется в файле OWconfig.BAK.

Если Вы не имеете доступа к root, то необходимо в ответе на вопрос:

Base directory [$OPENWINHOME/lib/locale/ru/X11]?

ввести имя каталога, куда для Вас разрешена запись. В этом каталоге будет создан подкаталог cyrfonts со шрифтами. Вместо корректировки $OPENWINHOME/server/etc/OWconfig в Вашем домашнем каталоге будет создан файл $HOME/.OWfontpath, содержащий необходимые управляющие структуры. Предыдущее содержимое файла .OWfontpath не сохраняется. Другие пользователи смогут применять эти шрифты только либо после выдачи команды xset +fp ..., либо скопировав себе Ваш файл .OWfontpath.

Итак, шрифты изготовлены и установлены. Необходимо проверить их наличие и доступность. Перезагрузите OpenWindows, а затем наберите в окне " Командное окно..." (cmdtool):

$ $OPENWINHOME/bin/xlsfonts | grep "roy international"

Вы должны получить следующие строчки:

-roy international-arial-bold-i-normal--0-0-0-0-p-0-cp1251-5
-roy international-arial-bold-i-normal--0-0-0-0-p-0-cp866-5
-roy international-arial-bold-i-normal--0-0-0-0-p-0-koi8-5
-roy international-arial-bold-r-normal--0-0-0-0-p-0-cp1251-5
-roy international-arial-bold-r-normal--0-0-0-0-p-0-cp866-5
-roy international-arial-bold-r-normal--0-0-0-0-p-0-koi8-5
-roy international-arial-medium-i-normal--0-0-0-0-p-0-cp1251-5
-roy international-arial-medium-i-normal--0-0-0-0-p-0-cp866-5
-roy international-arial-medium-i-normal--0-0-0-0-p-0-koi8-5
-roy international-arial-medium-r-normal--0-0-0-0-p-0-cp1251-5
-roy international-arial-medium-r-normal--0-0-0-0-p-0-cp866-5
-roy international-arial-medium-r-normal--0-0-0-0-p-0-koi8-5
-roy international-courier-bold-i-normal--0-0-0-0-m-0-cp1251-5
-roy international-courier-bold-i-normal--0-0-0-0-m-0-cp866-5
-roy international-courier-bold-i-normal--0-0-0-0-m-0-koi8-5
-roy international-courier-bold-r-normal--0-0-0-0-m-0-cp1251-5
-roy international-courier-bold-r-normal--0-0-0-0-m-0-cp866-5
-roy international-courier-bold-r-normal--0-0-0-0-m-0-koi8-5
-roy international-courier-medium-i-normal--0-0-0-0-m-0-cp1251-5
-roy international-courier-medium-i-normal--0-0-0-0-m-0-cp866-5
-roy international-courier-medium-i-normal--0-0-0-0-m-0-koi8-5
-roy international-courier-medium-r-normal--0-0-0-0-m-0-cp1251-5
-roy international-courier-medium-r-normal--0-0-0-0-m-0-cp866-5
-roy international-courier-medium-r-normal--0-0-0-0-m-0-koi8-5
-roy international-times-bold-i-normal--0-0-0-0-p-0-cp1251-5
-roy international-times-bold-i-normal--0-0-0-0-p-0-cp866-5
-roy international-times-bold-i-normal--0-0-0-0-p-0-koi8-5
-roy international-times-bold-r-normal--0-0-0-0-p-0-cp1251-5
-roy international-times-bold-r-normal--0-0-0-0-p-0-cp866-5
-roy international-times-bold-r-normal--0-0-0-0-p-0-koi8-5
-roy international-times-medium-i-normal--0-0-0-0-p-0-cp1251-5
-roy international-times-medium-i-normal--0-0-0-0-p-0-cp866-5
-roy international-times-medium-i-normal--0-0-0-0-p-0-koi8-5
-roy international-times-medium-r-normal--0-0-0-0-p-0-cp1251-5
-roy international-times-medium-r-normal--0-0-0-0-p-0-cp866-5
-roy international-times-medium-r-normal--0-0-0-0-p-0-koi8-5

Вызовите программу:

$ $OPENWINHOME/bin/xfontsel

В выпадающем меню fndry задайте roy international и, последовательно устанавливая доступные значения koi8, cp866, cp1251 в выпадающем меню rgstry, перебирайте значения в выпадающих меню fmly, wght и slant, контролируя наличие русских букв в окне вывода.

Правильность расположения символов можно проверить с помощью программы prfont.ps, входящей в состав пакета GNU PostScript.

%!
%%Creator: Eric Gisin 
%%Title: Print font catalog
% Copyright (c) 1986 Eric Gisin
% Copyright (C) 1992 Aladdin Enterprises, Menlo Park, CA 
(ghost@aladdin.com)
%   Modified to print all 256 encoded characters.
% Copyright (C) 1993 Aladdin Enterprises, Menlo Park, CA 
(ghost@aladdin.com)
%   Modified to print unencoded characters.
% Copyright (C) 1994 Aladdin Enterprises, Menlo Park, CA 
(ghost@aladdin.com)
%   Modified to always create 256-element Encoding vectors.
% Copyright (C) 1995 Aladdin Enterprises, Menlo Park, CA 
(ghost@aladdin.com)
%   Modified to print more than 128 unencoded characters.
% Copyright (C) 1996 Aladdin Enterprises, Menlo Park, CA 
(ghost@aladdin.com)
%   Modified to leave a slightly wider left margin, because many H-P
%     printers can't print in the leftmost 1/4" of the page.

% Example usages at bottom of file

/#copies 1 def
/min { 2 copy gt { exch } if pop } bind def

/T6 /Times-Roman findfont 6 scalefont def
/Temp 64 string def
/Inch {72 mul} def
/Base 16 def	% char code output base
/TempEncoding [ 256 { /.notdef } repeat ] def

% do single character of page
% output to rectangle ll=(0,-24) ur=(36,24)
/DoChar {
  /C exch def
  /S (_) dup 0 C put def
  /N F /Encoding get C get def

  % print code name, width and char name
  /W F setfont S stringwidth pop def
  T6 setfont
  N /.notdef ne {0 -20 moveto N Temp cvs show} if
  0 -12 moveto C Base Temp cvrs show (  ) show
  W 0.0005 add Temp cvs 0 5 getinterval show

  % print char with reference lines
  N /.notdef ne {
    3 0 translate
    0 0 moveto F24 setfont N glyphshow
    /W S stringwidth pop def
    0 -6 moveto 0 24 lineto
    W -6 moveto W 24 lineto
    -3 0 moveto W 3 add 0 lineto
    0 setlinewidth stroke
  } if
} def

% print page title
/DoTitle {
  /Times-Roman findfont 18 scalefont setfont
  36 10.5 Inch moveto FName Temp cvs show ( ) show ((24 point)) show
} def

% print one block of characters
/DoBlock {	% firstcode lastcode
  /FirstCode 2 index def
  1 exch {
    /I exch def
    /Xn I FirstCode sub 16 mod def /Yn I FirstCode sub 16 idiv def
    gsave
    Xn 35 mul 24 add Yn -56 mul 9.5 Inch add translate
    I DoChar
    grestore
  } for
} def

% print a line of character
/DoLine {	% firstcode lastcode
  1 exch { (_) dup 0 3 index put show pop } for
} def

% print font sample page
/DoFont {
  /FName exch def	% font name
  /F FName findfont def
  /F24 F 24 scalefont def
  /Line0 96 string def
  /Line1 96 string def

	% Display the first 128 encoded characters.

  DoTitle (, characters 0-127) show
  0 127 DoBlock
  F 10 scalefont setfont
  36 2.0 Inch moveto 0 63 DoLine
  36 1.5 Inch moveto 64 127 DoLine
  showpage

	% Display the second 128 encoded characters.

  DoTitle (, characters 128-255) show
  128 255 DoBlock
  F 10 scalefont setfont
  36 2.0 Inch moveto 128 191 DoLine
  36 1.5 Inch moveto 192 255 DoLine
  showpage

  F /FontType get 1 eq
   {
		% Find and display the unencoded characters.

	/Encoded F /Encoding get length dict def
	F /Encoding get { true Encoded 3 1 roll put } forall
	/Unencoded [ F /CharStrings get
	 { pop dup Encoded exch known { pop } if }
	forall ] def
	/Count Unencoded length def

		% Print the unencoded characters in blocks of 128.

	0 128 Unencoded length 1 sub
	 { dup 128 add Unencoded length min 1 index sub
	   Unencoded 3 1 roll getinterval TempEncoding copy
	   /BlockEncoding exch def
	   /BlockCount BlockEncoding length def
	   save
	   F length dict F
	    { 1 index /FID eq { pop pop } { 2 index 3 1 roll put } ifelse }
	   forall dup /Encoding TempEncoding put
	   /* exch definefont
	   /F exch def
	   /F24 F 24 scalefont def

	   DoTitle (, unencoded characters) show
	   0 BlockCount 1 sub DoBlock
	   F 10 scalefont setfont
	   36 2.0 Inch moveto 0 BlockCount 64 min 1 sub DoLine
	   BlockCount 64 gt
	    { 36 1.5 Inch moveto 64 BlockCount 128 min 1 sub DoLine
	    }
	   if

	   showpage
	   restore
	 } for

   }
  if

} def

% Do font samples
% /Times-Roman DoFont			% Test (less than a minute)
% /Hershey-Gothic-English DoFont	% Test (8 minutes)

% Do a complete catalog
% FontDirectory {pop DoFont} forall	% All fonts (quite a long time)

Запомните этот файл под именем prfont.ps, замените пятую строчку снизу

% /Times-Roman DoFont			% Test (less than a minute)

на

/ArialCyrKoi8  DoFont			% Test (less than a minute)

и откройте его в программе imagetool. Вы увидите красивую таблицу, содержащую много полезной информации о шрифте ArialKoi8. Проделайте эту операцию для ArialCP866 и ArialCP1251.


Copyright © 1997-2001, Vitaly Filatov, Moscow, Russia
Webmaster