Методика разработки сцен на PostScript Урок 1 | Урок1ПредисловиеКогда-то у меня было желание написать книгу, посвященную языкам описания страниц (PDL). Начал я с языка PostScript, как наиболее важного интересного в этой группе. Так в журнале PC Magazine/RE появилась серия статей под названием "Семь уроков по PostScript". К сожалению, их электронный вариант в редакции журнала не сохранился, однако у меня остались предшествующие версии, которые объединены в этом файле и предлагаются вашему вниманию. Утрачены тексты некоторых примеров и картинки с результатами исполнения примеров. Так как, похоже, что я из-за нехватки времени уже никогда не напишу задуманную книгу, то... Этот текст может свободно использоваться, модифицироваться и распространяться в любой форме. Автор же не несет за него ни малейшей ответственности. Занятие первоеЕсть два подхода к описанию языка PostScript: как к обычному языку программирования и как к языку описания страниц. В статье использован, в основном, первый подход, поэтому предполагается, что читатель имеет хоть какой-то опыт программирования. Язык PostScript был разработан Джоном Уорноком (John Warnock) в фирме Adobe Systems в 1982 г. История создания языка описана в предисловии одного из его авторов к "Справочному руководству по языку PostScript". PostScript создавался в качестве простого стандартного языка для описания вида текста, чертежей и простых изображений на печатаемой странице, что наложило определенный отпечаток на используемые в PostScript конструкции. Язык содержит около 250 операторов, что позволяет одни и те же действия запрограммировать самыми разными способами. С другой стороны разработчики не предполагали, что программы на PostScript будут большими, поэтому средства структуризации в языке не сильно развиты. Треть языка PostScript посвящена графике, остальное - это обычный процедурный язык программирования, который включает в себя элементы из многих других языков, но наиболее близок к языку Форт. Очень важно, что описание страниц на PostScript не зависит от устройства, на котором страница будет воспроизведена. Как правило программы на PostScript генерируются приложениями, например текстовыми процессорами, программами для настольных издательских систем, в частности CorelDrow, однако, как вы убедитесь сами, в ряде случаев знание этого языка может быть весьма полезным. Основные понятияОдной из причин, вызвавшей появление и расцвет языка PostScript является необходимость выводить текст и изображения на растровые внешние устройства: матричные, струйные и лазерные принтеры, а также экраны мониторов. Основное свойство таких устройств заключается в том, что изображение на них строится из массива прямоугольных элементов, называемых пикселами (от picture element - элемент изображения). Каждый пиксел имеет в этом массиве свой адрес - номер строки и номер столбца, где он расположен, а также цвет: у обычных матричных принтеров пикселы могут быть либо черного цвета, либо белого (в этом случае их часто называют точками); у лазерных принтеров пикселы имеют до 256 градаций серого цвета, у цветных мониторов - до сотен тысяч цветов. Устанавливая определенные пикселы в нужные цвета, мы получаем на экране текст и графические изображения. Так как у каждого растрового устройства пикселы имеют физические размеры, зависящие, например, от размера печатающих иголок матричного принтера или сетки на экране монитора, то число элементов изображения на единицу длины (обычно дюйм) называется разрешением растрового выводного устройства. В зависимости от этой характеристики устройства делятся на устройства с низким, средним и высоким разрешением. Для лазерных принтеров это соответственно до 300, 300-600 и более 600 dpi (точек на дюйм). Для каждого типа устройств границы этих классов свои, так для 14" мониторов разрешение более 50 dpi будет уже высоким. Чем выше разрешение, тем лучше качество изображения. PostScript-устройство (принтер, монитор) -- это устройство, в котором имеется интерпретатор языка PostScript. Интерпретатор PostScript принимает из компьютера текстовый файл с описанием страницы и преобразует его в растровую форму, которая и выводится на печать или на экран. (С этим и связана близкая к языку Форт структура PostScript -- она обеспечивает наименьший размер интерпретатора). Во время преобразования описания интерпретатор выполняет различные действия, зависящие от типа устройства. Так если на черно-белое печатающее устройство выводится полутоновое изображение, то интерпретатор PostScript этого устройство выполняет разбиение полутоновых областей на зоны с определенным уровнем серого цвета и заполняет каждую зону черными точками с плотностью, зависящей от этого уровня, что создает иллюзию полутонов на результирующем изображении. Передача описания страницы по многим причинам более выгодна, чем передача сразу всего массива составляющих страницу пикселов (растрового образа страницы). Во-первых, описание во много раз компактнее даже сильно сжатого изображения. Во-вторых, процесс подготовки печатной страницы требует значительного времени: если пересылается описание, то подготовкой к печати занимается процессор принтера или дисплейный процессор, что освобождает процессор персонального компьютера (ПК) для выполнения другой работы и тем самым повышает его производительность. И наконец, самое важное преимущество - это независимость описания от типа устройства. (Однако с интерпретатором языка PostScript можно работать и на самом ПК как работаем мы с Бейсиком или любым другим языком. Есть различные реализации интерпретаторов PostScript, но лучше воспользоваться общедоступной программой Gnostscript, работающей как под DOS, так и в Windows. Её можно, в частности, поискать в Internet. ) Чтобы обеспечить независимость описания страницы от всего разнообразия внешних растровых устройств в языке PostScript введено понятие текущей страницы. Текущая страница - "идеальная" страница в памяти, на которой рисует PostScript. Она не зависит от физических характеристик принтера, на который страница будет вводиться. В начале работы программы это совершенно чистая страница. Когда текущая страница полностью описана, она посылается на принтер, который распечатывает ее с таким качеством, которое способен обеспечить. Текущий путь (current path) - это набор соединенных между собой отдельных точек, линий, кривых, которые вместе описывают фигуры и их положение. На текущий путь не накладывается никаких ограничений (он может пересекать сам себя и т. д.) Элементы текущего пути задаются их позициями на текущей странице. Текущий путь обрезки (Current clipping path) -- это границы области, в которой может быть нарисовано изображение. Набор символов Все виды скобок (круглые, квадратные, фигурные, угловые) и знак процента являются для PostScript специальными знаками. Остальные символы -- подмножество кода ASCII используются в программе без ограничений и называются регулярными символами. Стек. PostScript резервирует для обрабатываемых данных часть памяти именуемую стеком. Данные, помещаемые в стек, извлекаются из него в обратном порядке, т. е. последнее записанное туда число удаляется первым. Такая дисциплина обслуживания называется LIFO. На самом деле PostScript оперирует четырьмя различными стеками: операндов, словарей, выполнения и состояния графики. Стек операндов - содержит собственно объекты PostScript и результаты действий над ними. Операторы PostScript получают операнды только через стек. Типы данных. Как и другие распространенные языки программирования PostScript поддерживает различные типы данных, включая integer, real, boolean, массивы и строки. В нём определяются также объекты типа mark (отметка, метка) и dictionary (словарь). Примеры записи целых чисел: 345 -87 38554 0 +57 Если величина числа превышает предел для представления целых чисел, оно автоматически конвертируется интерпретатором в число типа real. Примеры записи действительных чисел: -2.0 12.3 2E-5 0.0 345.6e8 -.025 Беззнаковые целые числа могут быть записаны в любой из 35 систем счисления с использование префикса в виде: база#число где:
16#cb2e 2#11001011 8#377 Строка - это последовательность символов, заключенная в круглые скобки. Система координат.Позиция элемента на странице описывается парой координат х,у. Каждое выходное устройство имеет встроенную систему координат, с помощью которой адресуются точки на странице. Эту систему будем называть пространством устройства (device space). Оно отличается от устройства к устройству. Нет единообразия в расположении начала координат, а также масштабов по вертикальной и горизонтальной осям. Позиция на текущей PostScript-странице описывается в системе координат пользователя (или в пространстве пользователя), которая не зависит от пространства устройства. Координаты PostScript-программе перед печатью текущей страницы автоматически преобразуются из пространства пользователя в пространство устройства. Пространство пользователя таким образом представляет систему координат, внутри которой страница может быть описана независимо от конкретной машины, где эта страница будет напечатана. Пространство пользователя может быть изменено тремя способами:
Постфиксная нотация (обратная польская запись).Операции над данными в PostScript требуют, чтобы их операнды сначала были помещены в стек. Такой стиль программирования, при котором операнды задаются до операции над ними (оператора) называется постфиксной нотацией. Так запись операции сложения двух чисел, допустим 4+5, в PostScript будет выглядеть так: 4 5 add О гибкости языка.Несмотря на большое количество встроенных операторов в PostScript нет зарезервированных слов. Любое слово переопределяемо. Программа в PostScript может рассматриваться как данные и это сближает его с языками типа Лисп. Переносимость программ.Программы на PostScript записываются с использованием только печатаемых символов кода ASCII, что позволяет обращаться с ними, как с обычными файлами, т. е. не возникает никаких проблем при пересылке таких файлов по сетям. Стек и арифметические операцииЭлементы данных в языке PostScript называются объектами (числа, массивы, строки, символы). Над объектами можно производить различные действия, но если в других языках объекты помещаются в переменные и адресуются указанием имени переменной, то PostScript работает с данными напрямую, используя механизм стека. Занесение чисел в стек.Любое число, появившееся в исходном файле PostScript-программы заносится в стек. Например, строку: -8 10.4 +77 интерпретатор по мере ее чтения слева направо выполнит следующие действия:
Стек будет иметь вид: 77 10.4 -8 На вершине стека число 77 и оно может быть использовано первым в какой-либо операции. Остальные числа используются в порядке обратном порядку их занесения в стек. Таким же образом в стек могут быть занесены PostScript-объекты любого вида: массивы, строки и такие экзотические объекты этого языка как словари. Для упрощения объяснений рассмотрим сначала операции в стеке над числами. Обратите внимание, что пробелы, символы табуляции и новой строки являются в PostScript-программе разделителями объектов, другие символы типа круглых и квадратных скобок в некоторых случаях также могут быть разделителями. Арифметические операторыОператор в PostScript - это слово, заставляющее интерпретатор выполнять те или иные действия. Он эквивалентен командам или процедурам в других языках программирования. Когда интерпретатор встречает слово в PostScript-программе, он просматривает свой внутренний словарь и пытается определить, является ли это слово именем оператора. Если оно в словаре найдено, то выполняются все связанные с ним действия, а затем переходит к следующему слову в исходном файле. add и sub. Операторы смотрят находятся ли в стеке их операнды. В общем случае оператор удаляет их из стека и помещает туда результат выполнения своих действий. Например, оператор add (сложение) удаляет из стека два верхних числа, складывает их и оставляет сумму в стеке. Так строка программы, приведенная ниже, будет влиять на стек как показано на рисунке. Аналогично работает оператор sub, вычитающий число, находящееся в вершине стека, из числа, лежащего в стеке следующим. Другие арифметические операторы: div - деление. Второе число делится на число в вершине стека. 13 8 div -> 1.625 idiv - целочисленное деление. 25 3 idiv -> 8 mod - второе число делится на число в вершине стека, сохраняя остаток от деления. 7 5 mod -> 8 Операнды операторов mod и idiv должны быть целыми числами. mul - перемножает два числа в вершине стека, помещая вместо них их произведение. 8 9 mul -> 72 neg - изменяет знак числа, находящегося в вершине стека. -37 neg -> 37 Запись арифметических выражений.Выражение 5+(8/2) на языке PostScript можно представить несколькими способами: 8 2 div 5 add либо 5 8 2 div add Чуть более сложный случай, выражение 9-(4*7), можно записать минимум двумя способами: 9 4 7 mul sub 4 7 mul 9 exch sub Во втором способе введен новый оператор exch. Он меняет местами положение двух верхних чисел в вершине стека. Применение оператора exch вызвано тем, что sub вычитает число в вершине стека из следующего за ним, что без exch приводит к неверному порядку действий. Действия над стеком.Эта группа операторов, представителем которой был exch добавляет, удаляет и изменяет порядок следования элементов в стеке. clear очистка стека - удаляет из стека все элементы а1...аn clear - 11 6 17 clear -> - count число элементов в стеке. a1...an count a1...an n dup дублирует в стеке его верхний элемент a1 dup a1 a1 8 dup -> 8 8 popудаляет из стека его верхний элемент an...a2 a1 pop an...a2 25 31 4 pop -> 25 31 roll вращает элементы стека, из стека извлекаются два числа. Верхнее говорит сколько раз и в каком направлении вращать элементы стека, второе - сколько элементов вращать. 7 8 9 3 1 roll -> 9 7 8 7 8 9 3 -1 roll -> 8 9 7 copy дублирует n верхних элементов стеков a1...an n copy a1...an a1...an Существует еще ряд более специального вида операторов, работающих со стеком, они будут рассмотрены по мере изложения. Ряд принтеров, например Apple LaserWriter, позволяет интерактивно с ними взаимодействовать. Вот операторы для этого: == удаляет элемент из вершины стека и отображает его на экране. Pstack - печатает все содержимое стека, не изменяя его. Pstack и == являются полиморфными операторами, так как они в качестве операндов принимают объекты многих типов. Начала графикиЯзык PostScript был разработан для получения графических изображений, для этого у него имеется большой набор операторов. Рисование в PostScript начинается с конструирования пути на идеальной поверхности, называемой текущей страницей. Путь - набор прямых и кривых линий, определяющих область, которая будет заполнена, или траекторию, которая будет нарисована на текущей странице. Конструируя путь, необходимо решить, что с ним делать: мы можем нарисовать линию заданной толщины или заполнить его, чтобы создать непрерывное изображение. После того, как заполнение текущей страницы закончено, ее можно распечатать на физическом листе бумаги. Начнем с простой задачи: нарисуем вертикальную линию длиной 5" (дюймов). Это выполнит следующая программа: newpath 144 72 moveto 144 432 lineto stroke showpage Разберем этот пример строка за строкой. Оператор newpath читает текущую страницу и объявляет, что начато рисование новой страницы. Конструирование пути начинается переносом воображаемого пера в заданную точку. Это перо при его переносах не оставляет "следа" на бумаге. Положение пера в каждый конкретный момент называется текущей точкой на текущем пути. Оператор movedo переносит перо в точку, координаты которой заданы его операндами. он извлекает из стека два числа и рассматривает их как координаты х и у точки, которая становится текущей. В системе координат, принятой в PostScript по умолчанию, начало координат находится в нижнем левом углу страницы. Координата х увеличивается вправо, а у - при движении вверх. Единица длины в этой системе равна 1/72 дюйма. Таким образом, оператор moveto переместит текущую точку (на рисунке - точка А) на два дюйма вправо (144/78) и один дюйм вверх (72/72). y | | .А | x o--------> Оператор lineto добавит сегмент к текущему пути, нарисуя линию между текущей точкой и точкой, координаты которой заданы его операндами, в данном случае 144 и 432. Точка, заданная как операнд lineto становиться текущей точкой. Обратите внимание, что lineto в действительности не рисует ничего на текущей странице. Он просто добавляет сегмент линии к текущему пути. Позже эту линию можно будет нарисовать, но это не происходит автоматически. Оператор stroke вызывает рисование сконструированного нами пути на текущей странице. Теперь этот путь становится видимой линией. И, наконец, оператор showpage печатает текущую страницу (отправляет ее на печать). Таким образом можно выделить 3 этапа построения:
Попробуйте написать программу, которая строит квадрат со стороной 1 см (1 дюйм = 2.54 см). 15.11.2001 |