Новости

О проекте

Зачем?

Используемое ПО

Методика разработки сцен на PostScript

Операторы языка PostScript

Библиотека

Изучение языка

Урок 1

Урок 2

Урок 3

Урок 4

Урок 5

Урок 6

Урок 7

Статьи

Ссылки...

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

Версии языка

До сих пор мы обходились без указания на различия в версиях различных языка 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       ->  a (версия) 

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

 product        ->  а (строка) 

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

 revision       ->  а (целое число) 

Вывод информации

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

 (строка) print 

== называется "два знака равно" (twoequals). Она введена в язык для удобства отладки.

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

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

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

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

 ceiling         -> а (целое число) 

Примеры:

   -1.9 ceiling  -> -1.0
    5.3 ceiling  ->  5.0
     49 ceiling  ->  49   

round -- возвращает целое число, ближайшее к ее операнду. Если аргумент дробная часть аргумента больше или равна 0.5, то возвращается большее целое число. Тип результата совпадает с типом операнда. Например:

   -1.9 round    -> -2.0
    8.5 round    ->  9.0
   -8.5 round    -> -7.0 

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

    1.9 truncate ->  1.0
   -3.4 truncate -> -3.0 

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

    1.9 floor    ->  1.0
   -3.7 floor    -> -4.0 

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

  17.83 cvi      ->   17
 -17.83 cvi      ->  -17

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

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

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

 /newstr 10 string def  %% объявляем строковую переменную
     1996 4 add newstr cvs       -> (2000)

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

 Синтаксис:
    Число СистемаСчисления Строка cvrs   -> (подстрока) 
 /tmp 14 string def            % строковая перемен на 14 символов
     99 10 temp cvrs   -> (99) % 99  представ в десятиричн системе счисления
    144 16 temp cvrs   -> (E0) % 144 представ в шестнадцатиричн системе счислен

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

 (abc) cvn    ->  /abc

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

Логические операторы

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

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

  bool1 bool2 xor  -> bool3
   int1  int2 xor  -> int3 
 true false xor   -> true 

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

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

  8.2 8.1 ge       -> true 

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

gt - больше чем

eq - равно

ne - не равно

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

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

bitshift -- логический сдвиг числа. Сдвигает двоичное представление целого числа integer1 влево на shift разрядов, если shift положительно, или вправо, если отрицательно. Возвращает результат 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

Контуры символов

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

Контурное или линейное описания символа могут быть непосредственно использованы в операторе charpath. Вместо рисования траектории оператор charpath добавляет её к текущей пути. Это позволяет производить над результатом различные операции заполнения отсечения и т.д. Он берет из стека строку и логическое выражение и добавляет к текущему пути контур символа, который описан в данной строке. Логическое выражение определяет тип оставляемого контура т.е. что произойдёт, если траектория символа предназначена для штриховки, а не для заполнения или оконтуривания. Если значение операнда false, то charpath просто добавляет траекторию символа, которая точно отображает описание символа в словаре шрифта, к текущему пути (результат удобный только для штрихового заполнения). Если операнд true, то charpath применяет к траектории символа оператор strokepath и полученный результат можно использовать для заливки каким-либо цветом (но не для штриховки). Если все символы шрифта будут заливаться, то разницы не видно. Оператор charpath не работает с теми частями символа, которые определенны как изображения или маски не являющиеся траекториями. Например:

(B) false charpath
(B) true charpath

Следует учесть, что контуры некоторых шрифтов защищены. в реализации языка PostScript Level 1 это относится ко всем шрифтам, в PostScript Level 2 - только некоторых специальных шрифтов и не относится к обычным шрифтам Type 1 или Type 3. Если текущий шрифт защищён, использование charpath, чтобы получить их контуры, вызывает блокирование работы операторов pathforall и upath до тех пор пока контуры символов из такого шрифта остаются в текущей траектории.

Путь построенный с помощью charpath может быть вычерчен либо заполнен (залит).

Пример использования тривиальная рекламная виньетка с названием вашей фирмы. Для этого поэспериментируйте с текстом этой процедуры.

    /Helvetica-Bold findfont  % Устанавливаем шрифт
                 24 scalefont
                    setfont
    /oshow {             % Добавляем строку к текущему пути
      true charpath
      stroke
    } def

    /CircleName {  % рисуем фигуру из текста
      30 30 360 %% угол поворота от 30 до 360 шаг 30
     {          %% входим в цикл
       gsave     % сохранили оригин ориентацию осей
         rotate  % повернули оси на текущ угол
         0 0 moveto      % печатаем в начале координат
         (   PostScript) oshow % вот его и печатаем
         grestore % восстановлил оригин ориентацию осей
     } for
    } def

    %%%% Основная программа %%%%
150 350 translate     % печатаем в середине страницы
     .3 setlinewidth  % ширина контура букв
        CircleName
        gsave         % сохраним нарисован путь
    0.8 setgray fill  % заливаем его сереньким
        grestore      % восстановили нарисован путь
        stroke        % обводим буквы
showpage

Траектория отсечения

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

Например, следующая программа конструирует траекторию в виде треугольника и делает его траекторией отсечения. Затем она рисует прямоугольную сетку и после печати мы видим, что осталось только та часть сетки, которая попала в этот прямоугольник.

  /inch {72 mul} def  % перевод дюймы в пункты

  /triangle {         % рисуем треугольник
                   newpath
    0      0        moveto
    2 inch 0        lineto
    1 inch 2.8 inch lineto
                    closepath
  } def

  /vgrid {            % рисуем вертикальн сетку
         newpath
   0 9 2 inch         % от 0 до 2 дюймов с шагом 9 пунктов
   {
     0   exch moveto
     0 3 inch rlineto % рисуем вертикальн линию длиню 3 дюйма
   } for
   stroke             % нарисован сетку обводим
  } def

 /hgrid  {            % рисуем горизонтальн сетку
           newpath    % аналогично вертикальн
  0 10 2.8 inch
  {
    0   exch moveto
    2 inch 0 rlineto
  } for
  stroke
 } def

%%%% Основная программа %%%%
 200 300 translate  % здесь и рисуем
 triangle clip      % делаем треугольник областью отсечения
 vgrid           % ну и сеточку рисуем
 hgrid
showpage 

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

21.11.2001



©Фурашев А. 2002
e-mail

Хостинг от uCoz