Методика разработки сцен на PostScript Урок 5 | Занятие пятоеВерсии языкаДо сих пор мы обходились без указания на различия в версиях различных языка 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 |