Семь уроков по PostScript

         

Кодирование шрифта


Каждый словарь шрифта содержит описание символов в соответствии с некоторой кодовой таблицей, в частности это может быть ASCII. Таким образом каждый символ имеет свой цифровой код -- число от 0 до 255. Кодовая таблица не является постоянной, ее можно изменять из приложения.

Коды символов можно использовать двумя способами:

- их можно с помощью оператора put вставлять в строку;

- или непосредственно использовать в строке в виде восьмеричных чисел.

Многие шрифты имеют символы не входящие в стандартную кодировку и кроме того, часто такие символы отсутствуют на клавиатуре. Чтобы посмотреть как кодируются символы того или иного шрифта, напишем программу, которая распечатывает кодовую таблицу любого заданного шрифта.

/Helvetica findfont 12 scalefont setfont

/cod 3 string def

/char 1 string def

/newline

{currentpoint 13 sub

exch pop LM

exch moveto }def

/prtnum        % в стеке код

{cod cvs show}def

/prtchar       %в стеке код

{char 3 - 1 0 roll put

char show}def

/prtall

{dup prtnum () show

prtchar newline} def

% основная программа.

/LM 72 def

LM 450 moveto

12 1 60 {prtall} for

/LM 144 def

LM 144 moveto

6 1 100 {prtall} for

showpage

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

и у.

Графическое состояние программы работает с текущей матрицей трансформирования, определяющей, как на текущей странице позиционируются все изображения.

Операторы translate, rotate и scale для модификации координат пространства пользователя изменяет соответствующие элементы этой матрицы.

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


Чтобы изменить масштаб шрифта по х и по у, нужно задать соответственно значения чисел m и n в матрице

[m 0 0 n 0 0 ]

Так строки

/Helvetica findfont 6 scalefont

/Helvetica findfont [6 0 0 6 0 0] makefont

выполняют ровно одно и тоже: создают шрифт Helvetica размером 6 пунктов. Действие оператора makefont однако значительтно шире, чем у scalefont. Он позволяет как угодно сжимать и растягивать текст. Следующая прграмма из “Голубой книги” показывает технику работы с makefont.

/basefont /Helvetica findfont def

/LM 72 def

/newline

{currentpoint 13 sub

 exch pop LM

 exch moveto} def

% основная программа

LM 400 moveto

% обычная печать

basefont [12 0 0 12 0 0] makefont setfont

(Пример нормальной печати) show newline

% растянутый.

basefont [17 0 0 12 0 0] makefont setfont

(Растянутый шрифт) show newline

% сжатый

basefont [7 0 0 12 0 0] makefont setfont

(Сжатый шрифт) show newline

% наклонный

basefont [12 0 6.93 12 0 0] makefont

setfont

(Italic) show

showpage

<рис. файл p4_4.ps>

Программа печатает четыре строки, каждый раз преобразуя текущий шрифт, с помощью различных матриц шрифта. Во второй и третьей строке изменялся масштаб по горизонтали (Вы можете поэксперементировать, задавая различный масштаб и по вертикали, но не забудьте поменять константу в процедуре newline, чтобы строки не наползали одна на другую). Интересна последняя строка. Третье число в матрице 6.93 представляет собой результат умножения у на tg 30 градусов. Таким образом задан наклон шрифта.

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

Все эти преобразования пространства пользователя можно выполнить также с помощью операторов scale и setmatrix. Однако  в отличие от makefont их действие распространяется на все, что печатается на текущей странице. Если нужно сжать, растянуть или наклонить текст, то следует пользоваться только makefont.

Занятие пятое

До сих пор мы обходились без указания на различия в версиях различных языка PostScript, но сейчас это необходимо сделать. Начнём с небольшого экскурса в историю языка.



Итак язык PostScript был разработан фирмой Adobe Systems в 1985. За эти годы он активно развивался: в следующих версиях добавилась работа с цветом, изображениями и т.д. Реализации PostScript организованы по уровням. Различают языки PostScript Level 1 более поздний , PostScript Level 2. Отметим, что ядро языка при этом не изменилось. PostScript Level 2 адаптирован для новых технологий печати, в него добавлено около 150 новых операторов, оформленных в виде расширений языка. Для нас важно, что эти реализации языка совместимы снизу-вверх, т. е. программа, написанная для реализации Level 1 будет выполнена в интерпретатором для PostScript Level 2. Далее мы будем помечать операторы, относящиеся к Level 2 знаком (L2).

Есть несколько способов определить, какой уровень языка поддерживает ваше оборудование, его название, версию и номер релиза.

languagelevel – определение поддерживаемого уровня языка.

Синтаксис: -- languagelevel à уровень

Уровень – это целое число, обозначающее уровень языка PostScript, поддерживаемый интерпретатором. Если он равен 2, то интерпретатором поддерживается язык PostScript Level 2. Если 1 или слова нет в словаре systemdict, то интерпретатор не поддерживает Level 2.

version -- возвращает строку, которая идентифицирует используемую версию интерпретатора языка PostScript. Эта идентификация не включает информацию о возможностях языка, аппаратных средствах или операционной среде, в которой работает интерпретатор.

Синтаксис: -- version à - версия

product -- возвращает объект типа строки только для чтения, содержащую название продукта, в котором исполняется интерпретатор языка PostScript.

Синтаксис: -- product à

строка

 

revision

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

Синтаксис: -- revision à - int



Печать

print

-- записывает символы строки в стандартный файл вывода. Оператор print предоставляет простое средство для пересылки текста приложению или пользователю. Этот оператор не рисует символы на текущей странице (для этого используется операторы show и showpage).

Синтаксис: строка print à --

Следующая встроенная процедура == носит название “два знака равно” (twoequals). Она введена в язык для удобства отладки.

Синтаксис: что-либо == à--

== извлекает объект из стека операндов, создаёт его текстовое представление, близкое по форме к синтаксиссу PostScript, помещает вслед за ним знак перевода строки и записывает результат на стандартное устройство вывода. Имя == не является специальным: в программе на PostScript оно может быть разделено “белыми” пробелами или специальными символами, как и имя составленное из букв.

Встроенные функции

Некоторые встроенные функции были рассмотрены на первом занятии. Сейчас мы добавим к ним ещё десяток, связанных с работой с числами.

ceiling -- возвращает ближайшее целое число, большее или равное операнду из вершины стека. Тип результата совпадает с типом операнда.

Синтаксис: число1 ceiling à число2

Примеры.

-1.9 ceiling à -1.0

5.3 ceiling à

5.0

49 ceiling à 49

round

-- возвращает целое число, ближайшее к ее операнду. Если аргумент дробная часть аргумента равна 0,5 (т. е. он одинаково удалён от соседних целых чисел), то возвращается большее целое число. Тип результата совпадает с типом операнда.

Синтаксис: число1 round à число2

Примеры.

-1.9 round à

-2.0

8.5 round à 9.0

-8.5 round à

-7.0

Index</A><BR>

truncate возвращает целую часть своего операнда.

Синтаксис: число1 truncate à число2

Примеры.

1.9 truncate à 1.0

-3.4 truncate à -3.0 <BR>

floor -- возвращает наибольшее целое число меньшее или равное операнду.

Синтаксис: число1 floor à число2



Примеры.

1.9 floor à 1.0

-3.7 floor à

-4.0 <BR>

cvi – берёт из стека число типа integer, real или строку и конвертирует его в целое число. У чисел типа real отбрасывается дробная часть, но, если это число больше максимально представимого в виде целого, возникает ошибка. Строка рассматривается как последовательность символов с записью числа в принятой в PostScript нотации.

Синтаксис:

число1

cvi à целое_число2

строка cvi à целое_число2

Примеры.

17.83 cvi à 17

-17.83 cvi à

-17

cvlit -- конвертирует объект из вершины стека операндов из исполняемой формы в литерал.

Синтаксис:

оператор cvlit à литерал

cvr -- работает аналогично cvi, только результат преобразования – число типа real.

Синтаксис:

число1

cvr à real

строка cvi à real

cvs – конвертирование в строку. Создаёт текстовое представление произвольного объекта

что-либо, записывает его в строку (стирая то, что было в строке ранее) и возвращает подстроку.

Если объект число, то возвращается его строковое представление. Для логических объектов возвращается строка со соловом true или false. Строку cvs просто копирует в другую строку. Если объект имя или оператор, cvs возвращает текстовое представление этого имени или оператора. Во всех других случаях возвращается текст --nostringval--.

Синтаксис: что-либо  строка cvs à подстрока

Пример.

/newstr 10 string def

1996 4 add newstr cvs à (2000)

 

cvrs – конвертирование в строку в заданной системе счисления. Работает как cvs, но при конвертировании результат записывается в заданной системе счисления. Если она десятичная, то ничем не отличается от cvs (или cvi, если число типа integer).

Синтаксис:

число система_счисления строка cvrs à

подстрока

Примеры.

/tmp 14 string def

99 10 temp cvrs à

(99)

144 16 temp cvrs à (E0)

cvn – конвертирует строку операнда в имя объекта, совпадающее с ней лексически. Имя объекта исполняемо.



строка cvn à имя

Пример.

Синтаксис: (abc) cvn à

/abc

cvx – конвертирование в исполняемую форму. Делает литеральный объект что-либо из вершины стека операндов исполняемым. Возможность выполнить динамически создаваемую процедуру.

Синтаксис:

что-либо cvx à что-либо

Логические операторы в PostScript работают как с целыми числами, так и с логическими. В первом случае операция выполняется над операндом поразрядно. Имеется четыре основных логических операции: and, or, not и xor (из которых, как известно, можно построить все остальные булевские функции). Для краткости ниже дан пример только для xor.

 

xor – если оба операнда логические величины, то в стеке возвращается результат операции “исключающее ИЛИ”, если операнды – типа integer, в стек помещается результат поразрядной операции xor над их двоичным представлением.

 

Синтаксис:

bool1 bool2 xor à bool3

int1 int2 xor à int3

Пример.

true false xor à true

Операторы сравнения

ge – больше или равно.

Синтаксис:

число1 число2 ge à результат_сравнения

строка1 строка2 ge à

результат_сравнения

извлекает два объекта из стека операндов и помещает в него значение true, если первый операнд больше или равен второму. Строки сравниваются посимвольно.

Пример.

8.2   8.1 ge à

true

Аналогично работают и другие операторы сравнения:

gt – больше чем

eq – равно

ne – не равно

le – меньше равно

lt – меньше чем.

bitshift -- логический сдвиг числа. Сдвигает двоичное представление целого числа integer1 влево на shift разрядов, если shift положительно, или вправо, если отрицательно. Возвращает результат integer2. Биты исходящие теряются, а входящие -- обнуляются. Оба операнда должны быть целыми числами.

Синтаксис: integer1 shift bitshift à

integer2

Пример.

5 4 bitshift à

80

144 -3 bitshift à

56

Генерация случайных чисел



rand – помещает в стек случайное целое число типа integer в диапазоне от 0 до 231-1, полученное с помощью генератора псевдо-случайных чисел.

Синтаксис: -- rand à

int

rrand -- возвращает целое число, представляющее текущее состояние генератора случайных чисел, используемого оператором rand. Оно может быть затем использовано в качестве операнда оператора srand, чтобы возобновить генерацию случайных чисел с текущей позиции в последовательности получаемых с его помощью чисел.

Синтаксис:  -- rrand à

int

Время

realtime -- возвращает отсчет таймера, считающего реальное время независимо от интерпретатора PostScript. Минимальный интервал отсчитываемого времени равен одной миллисекунде, начальное значение и частота обновления счётчика произвольны и зависят от реализации. Как только значение счётчика времени станет больше, чем максимально большое целое число, интерпретатор меняет его на 0 или, в некоторых реализациях на наименьшее целое (наибольшее отрицательное) число. (L2).

Синтаксис: -- realtime à

int

usertime – возвращает значения интервального таймера, который увеличивается на 1 за каждую миллисекунду работы интерпретатора PostScript. Это значение никак не связано с календарным временем. При достижении предельного значения счётчика он, в зависимости от реализации, устанавливается либо равным нулю, либо наибольшему отрицательному целому числу.

Синтаксис: -- usertime à

int


Содержание раздела